1+ const logger = require ( '../../config/logger' ) . mainLogger ;
2+
3+ /**
4+ *
5+ * @param run Must be populated with map and tiletypes!
6+ * @returns {number }
7+ */
8+ module . exports . calculateLineScore = function ( run ) {
9+ try {
10+ let score = 0 ;
11+ let final_score ;
12+ let multiplier = 1.0 ;
13+
14+ let lastCheckPointTile = 0 ;
15+ let checkPointCount = 0 ;
16+
17+ let total_lops = 0 ;
18+ for ( let i = 0 ; i < run . LoPs . length ; i ++ ) {
19+ total_lops += run . LoPs [ i ] ;
20+ }
21+
22+ for ( let i = 0 ; i < run . tiles . length ; i ++ ) {
23+ const tile = run . tiles [ i ] ;
24+ for ( let j = 0 ; j < tile . scoredItems . length ; j ++ ) {
25+ switch ( tile . scoredItems [ j ] . item ) {
26+ case 'checkpoint' :
27+ const tileCount = i - lastCheckPointTile ;
28+ score +=
29+ Math . max ( tileCount * ( 5 - 2 * run . LoPs [ checkPointCount ] ) , 0 ) *
30+ tile . scoredItems [ j ] . scored ;
31+ lastCheckPointTile = i ;
32+ checkPointCount ++ ;
33+ break ;
34+ case 'gap' :
35+ score += 10 * tile . scoredItems [ j ] . scored ;
36+ break ;
37+ case 'intersection' :
38+ score += 10 * tile . scoredItems [ j ] . scored * tile . scoredItems [ j ] . count ;
39+ break ;
40+ case 'obstacle' :
41+ score += 20 * tile . scoredItems [ j ] . scored * tile . scoredItems [ j ] . count ;
42+ break ;
43+ case 'speedbump' :
44+ score += 10 * tile . scoredItems [ j ] . scored ;
45+ break ;
46+ case 'ramp' :
47+ score += 10 * tile . scoredItems [ j ] . scored * tile . scoredItems [ j ] . count ;
48+ break ;
49+ case 'seesaw' :
50+ score += 20 * tile . scoredItems [ j ] . scored * tile . scoredItems [ j ] . count ;
51+ break ;
52+ }
53+ }
54+ }
55+
56+
57+ let error = 1 ;
58+ if ( run . rescueOrder ) {
59+ let liveCount = 0 ;
60+ for ( let victim of run . rescueOrder ) {
61+ if ( victim . victimType == "LIVE" && victim . zoneType == "RED" ) continue ;
62+ if ( victim . victimType == "DEAD" && victim . zoneType == "GREEN" ) continue ;
63+ if ( victim . victimType == "DEAD" && liveCount != run . map . victims . live ) continue ;
64+
65+ multiplier *= Math . max ( 1400 - ( 50 * run . LoPs [ run . map . EvacuationAreaLoPIndex ] ) , 1250 ) ;
66+
67+ error *= 1000 ;
68+ if ( victim . victimType == "LIVE" ) liveCount ++ ;
69+ }
70+ multiplier /= error ;
71+ }
72+
73+ if ( run . exitBonus ) {
74+ score += Math . max ( 60 - 5 * total_lops , 0 ) ;
75+ const tileCount = run . tiles . length - lastCheckPointTile - 1 ;
76+ score += Math . max ( tileCount * ( 5 - 2 * run . LoPs [ checkPointCount ] ) , 0 )
77+ }
78+
79+ // 5 points for placing robot on first droptile (start)
80+ // Implicit showedUp if anything else is scored
81+ if ( run . showedUp || score > 0 ) {
82+ score += 5 ;
83+ }
84+
85+ final_score = Math . round ( score * multiplier ) ;
86+
87+ const ret = { } ;
88+ ret . raw_score = score ;
89+ ret . score = final_score ;
90+ ret . multiplier = multiplier ;
91+ return ret ;
92+ } catch ( e ) {
93+ console . log ( e ) ;
94+ }
95+ } ;
96+
97+ /**
98+ *
99+ * @param run Must be populated with map!
100+ * @returns {number }
101+ */
102+ module . exports . calculateMazeScore = function ( run ) {
103+ let score = 0 ;
104+
105+ const mapTiles = [ ] ;
106+ for ( let i = 0 ; i < run . map . cells . length ; i ++ ) {
107+ const cell = run . map . cells [ i ] ;
108+ if ( cell . isTile ) {
109+ mapTiles [ `${ cell . x } ,${ cell . y } ,${ cell . z } ` ] = cell ;
110+ }
111+ }
112+
113+ let victims = { } ;
114+ let rescueKits = 0 ;
115+
116+ for ( let i = 0 ; i < run . tiles . length ; i ++ ) {
117+ const tile = run . tiles [ i ] ;
118+ const coord = `${ tile . x } ,${ tile . y } ,${ tile . z } ` ;
119+
120+ if ( tile . scoredItems . speedbump && mapTiles [ coord ] . tile . speedbump ) {
121+ score += 5 ;
122+ }
123+ if ( tile . scoredItems . checkpoint && mapTiles [ coord ] . tile . checkpoint ) {
124+ score += 10 ;
125+ }
126+ if ( tile . scoredItems . ramp && mapTiles [ coord ] . tile . ramp ) {
127+ score += 10 ;
128+ }
129+ if ( tile . scoredItems . steps && mapTiles [ coord ] . tile . steps ) {
130+ score += 10 ;
131+ }
132+
133+ const maxKits = {
134+ H : 2 ,
135+ S : 1 ,
136+ U : 0 ,
137+ Red : 2 ,
138+ Yellow : 1 ,
139+ Green : 0 ,
140+ } ;
141+
142+ if ( mapTiles [ coord ] . tile . victims . top != 'None' ) {
143+ if ( tile . scoredItems . victims . top ) {
144+ addVictimCount ( victims , mapTiles [ coord ] . tile . victims . top ) ;
145+ if (
146+ mapTiles [ coord ] . tile . victims . top == 'Red' ||
147+ mapTiles [ coord ] . tile . victims . top == 'Yellow' ||
148+ mapTiles [ coord ] . tile . victims . top == 'Green'
149+ )
150+ score += mapTiles [ coord ] . isLinear ? 5 : 15 ;
151+ else score += mapTiles [ coord ] . isLinear ? 10 : 30 ;
152+
153+ rescueKits += Math . min (
154+ tile . scoredItems . rescueKits . top ,
155+ maxKits [ mapTiles [ coord ] . tile . victims . top ]
156+ ) ;
157+ }
158+ }
159+ if ( mapTiles [ coord ] . tile . victims . right != 'None' ) {
160+ if ( tile . scoredItems . victims . right ) {
161+ addVictimCount ( victims , mapTiles [ coord ] . tile . victims . right ) ;
162+ if (
163+ mapTiles [ coord ] . tile . victims . right == 'Red' ||
164+ mapTiles [ coord ] . tile . victims . right == 'Yellow' ||
165+ mapTiles [ coord ] . tile . victims . right == 'Green'
166+ )
167+ score += mapTiles [ coord ] . isLinear ? 5 : 15 ;
168+ else score += mapTiles [ coord ] . isLinear ? 10 : 30 ;
169+
170+ rescueKits += Math . min (
171+ tile . scoredItems . rescueKits . right ,
172+ maxKits [ mapTiles [ coord ] . tile . victims . right ]
173+ ) ;
174+ }
175+ }
176+ if ( mapTiles [ coord ] . tile . victims . bottom != 'None' ) {
177+ if ( tile . scoredItems . victims . bottom ) {
178+ addVictimCount ( victims , mapTiles [ coord ] . tile . victims . bottom ) ;
179+ if (
180+ mapTiles [ coord ] . tile . victims . bottom == 'Red' ||
181+ mapTiles [ coord ] . tile . victims . bottom == 'Yellow' ||
182+ mapTiles [ coord ] . tile . victims . bottom == 'Green'
183+ )
184+ score += mapTiles [ coord ] . isLinear ? 5 : 15 ;
185+ else score += mapTiles [ coord ] . isLinear ? 10 : 30 ;
186+
187+ rescueKits += Math . min (
188+ tile . scoredItems . rescueKits . bottom ,
189+ maxKits [ mapTiles [ coord ] . tile . victims . bottom ]
190+ ) ;
191+ }
192+ }
193+ if ( mapTiles [ coord ] . tile . victims . left != 'None' ) {
194+ if ( tile . scoredItems . victims . left ) {
195+ addVictimCount ( victims , mapTiles [ coord ] . tile . victims . left ) ;
196+ if (
197+ mapTiles [ coord ] . tile . victims . left == 'Red' ||
198+ mapTiles [ coord ] . tile . victims . left == 'Yellow' ||
199+ mapTiles [ coord ] . tile . victims . left == 'Green'
200+ )
201+ score += mapTiles [ coord ] . isLinear ? 5 : 15 ;
202+ else score += mapTiles [ coord ] . isLinear ? 10 : 30 ;
203+
204+ rescueKits += Math . min (
205+ tile . scoredItems . rescueKits . left ,
206+ maxKits [ mapTiles [ coord ] . tile . victims . left ]
207+ ) ;
208+ }
209+ }
210+ }
211+
212+ let totalVictimCount = sum ( Object . values ( victims ) ) ;
213+
214+ score += Math . min ( rescueKits , 12 ) * 10 ;
215+
216+ score += Math . max ( ( totalVictimCount + Math . min ( rescueKits , 12 ) - run . LoPs ) * 10 , 0 ) ;
217+
218+ if ( run . exitBonus ) {
219+ score += totalVictimCount * 10 ;
220+ }
221+
222+ score -= Math . min ( run . misidentification * 5 , score ) ;
223+
224+ return {
225+ score : score ,
226+ victims : convert ( victims ) ,
227+ kits : Math . min ( rescueKits , 12 )
228+ }
229+ } ;
230+
231+ function addVictimCount ( obj , type ) {
232+ if ( obj [ type ] == null ) obj [ type ] = 0 ;
233+ obj [ type ] ++ ;
234+ }
235+
236+ function sum ( array ) {
237+ if ( array . length == 0 ) return 0 ;
238+ return array . reduce ( function ( a , b ) {
239+ return a + b ;
240+ } ) ;
241+ }
242+
243+ function convert ( obj ) {
244+ return Object . entries ( obj ) . map ( o => {
245+ return {
246+ 'type' : o [ 0 ] ,
247+ 'count' : o [ 1 ]
248+ }
249+ } )
250+ }
0 commit comments