1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2 // Licensed under the MIT License:
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 
22 module capnproto.benchmark.CatRank;
23 
24 import capnproto.StructList;
25 import capnproto.Text;
26 
27 import capnproto.benchmark.catrankschema;
28 import capnproto.benchmark.Common;
29 import capnproto.benchmark.TestCase;
30 
31 void main(string[] args)
32 {
33 	auto testCase = new CatRank();
34 	testCase.execute(args);
35 }
36 
37 final class CatRank : TestCase!(SearchResultList, SearchResultList, int)
38 {
39 public: //Types.
40 	struct ScoredResult
41 	{
42 	public:
43 		double score;
44 		SearchResult.Reader result;
45 	}
46 
47 public: //Methods.
48 	override int setupRequest(SearchResultList.Builder request)
49 	{
50 		import std.array : appender;
51 		
52 		int count = fastRand(1000);
53 		int goodCount = 0;
54 		
55 		auto list = request.initResults(count);
56 		foreach(i; 0..count)
57 		{
58 			auto result = list[i];
59 			result.setScore(1000 - i);
60 			int urlSize = fastRand(100);
61 			
62 			static Text.Reader URL_PREFIX = "http://example.com";
63 			auto urlPrefixLength = URL_PREFIX.length;
64 			auto url = result.initUrl(cast(int)(urlSize + urlPrefixLength));
65 			auto bytes = url.asByteBuffer();
66 			auto bb = URL_PREFIX.asByteBuffer();
67 			bytes.put(bb);
68 			
69 			foreach(j; 0..urlSize)
70 				bytes.put(cast(byte)(97 + fastRand(26)));
71 			
72 			bool isCat = fastRand(8) == 0;
73 			bool isDog = fastRand(8) == 0;
74 			goodCount += isCat && !isDog;
75 			
76 			static snippet = appender!(char[]);
77 			snippet.clear();
78 			snippet ~= " ";
79 			
80 			int prefix = fastRand(20);
81 			foreach(j; 0..prefix)
82 				snippet ~= WORDS[fastRand(cast(uint)WORDS.length)];
83 			if(isCat)
84 				snippet ~= "cat ";
85 			if(isDog)
86 				snippet ~= "dog ";
87 			
88 			int suffix = fastRand(20);
89 			foreach(j; 0..suffix)
90 				snippet ~= WORDS[fastRand(cast(uint)WORDS.length)];
91 			
92 			result.setSnippet(cast(string)snippet.data());
93 		}
94 		
95 		return goodCount;
96 	}
97 	
98 	override void handleRequest(SearchResultList.Reader request, SearchResultList.Builder response)
99 	{
100 		import std.algorithm : sort;
101 		import std.array : appender;
102 		import std.string : indexOf;
103 		
104 		static scoredResults = appender!(ScoredResult[]);
105 		scoredResults.clear();
106 		
107 		foreach(result; request.getResults())
108 		{
109 			double score = result.getScore();
110 			auto snippet = result.getSnippet();
111 			if(snippet.indexOf(" cat ") != -1)
112 				score *= 10000;
113 			if(snippet.indexOf(" dog ") != -1)
114 				score /= 10000;
115 			scoredResults ~= ScoredResult(score, result);
116 		}
117 		
118 		scoredResults.data().sort!((a,b) => a.score > b.score);
119 		
120 		auto list = response.initResults(cast(int)scoredResults.data().length);
121 		foreach(i,result; scoredResults.data())
122 		{
123 			auto item = list.get(i);
124 			item.setScore(result.score);
125 			item.setUrl(result.result.getUrl());
126 			item.setSnippet(result.result.getSnippet());
127 		}
128 	}
129 	
130 	override bool checkResponse(SearchResultList.Reader response, int expectedGoodCount)
131 	{
132 		int goodCount = 0;
133 		foreach(result; response.getResults())
134 		{
135 			if(result.getScore() > 1001)
136 				++goodCount;
137 			else
138 				break;
139 		}
140 		return goodCount == expectedGoodCount;
141 	}
142 }