OSDN Git Service

392f33f3c09dfa8d2e7970b2bd2a190ae529dea8
[kcd/KCD.git] / KCD / HMCalculateDamageCommand.m
1 //
2 //  HMCalculateDamageCommand.m
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2014/05/22.
6 //  Copyright (c) 2014年 Hori,Masaki. All rights reserved.
7 //
8
9 #import "HMCalculateDamageCommand.h"
10
11 #import "HMTemporaryDataStore.h"
12 #import "HMServerDataStore.h"
13
14
15 #define DAMAGE_CHECK 0
16
17 typedef NS_ENUM(NSUInteger, HMBattleType) {
18         typeNormal = 0,
19         typeCombinedAir,
20         typeCombinedWater,
21 };
22
23 @interface HMCalculateDamageCommand ()
24 @property (nonatomic, strong) HMTemporaryDataStore *store;
25 @property HMBattleType battleType;
26 @end
27
28 @implementation HMCalculateDamageCommand
29
30 - (id)init
31 {
32         self = [super init];
33         if(self) {
34                 _store = [HMTemporaryDataStore oneTimeEditor];
35         }
36         return self;
37 }
38
39 - (void)resetBattle
40 {
41         NSManagedObjectContext *moc = self.store.managedObjectContext;
42         
43         NSError *error = nil;
44         NSArray *array = [self.store objectsWithEntityName:@"Battle"
45                                                                                 predicate:nil
46                                                                                         error:&error];
47         if(error) {
48                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
49                 return;
50         }
51         for(id object in array) {
52                 [moc deleteObject:object];
53         }
54                 
55         [self.store saveAction:nil];
56 }
57
58 - (void)resetDamage
59 {
60         NSManagedObjectContext *moc = self.store.managedObjectContext;
61         
62         NSError *error = nil;
63         NSArray *array = [self.store objectsWithEntityName:@"Damage"
64                                                            predicate:nil
65                                                                    error:&error];
66         if(error) {
67                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
68                 return;
69         }
70         for(id object in array) {
71                 [moc deleteObject:object];
72         }
73                 
74         [self.store saveAction:nil];
75 }
76
77 - (void)startBattle
78 {
79         NSManagedObjectContext *moc = self.store.managedObjectContext;
80         
81         // Battleエンティティ作成
82         id battle = [NSEntityDescription insertNewObjectForEntityForName:@"Battle"
83                                                                                           inManagedObjectContext:moc];
84         
85         [battle setValue:@([[self.arguments valueForKey:@"api_deck_id"] integerValue]) forKeyPath:@"deckId"];
86         [battle setValue:@([[self.arguments valueForKey:@"api_maparea_id"] integerValue]) forKeyPath:@"mapArea"];
87         [battle setValue:@([[self.arguments valueForKey:@"api_mapinfo_no"] integerValue]) forKeyPath:@"mapInfo"];
88         [battle setValue:@([[self.json valueForKeyPath:@"api_data.api_no"] integerValue]) forKeyPath:@"no"];
89         
90         [self.store saveAction:nil];
91 }
92
93 - (void)updateBattleCell
94 {
95         NSError *error = nil;
96         NSArray *battles = [self.store objectsWithEntityName:@"Battle"
97                                                                                            predicate:nil
98                                                                                                    error:&error];
99         if(error) {
100                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
101         }
102         if(battles.count == 0) {
103                 NSLog(@"Battle is invalid.");
104                 return;
105         }
106         id battle = battles[0];
107         
108         id battleCell = [battle valueForKey:@"no"];
109         if([battleCell integerValue] == 0) {
110                 battleCell = nil;
111         }
112         if([self.api hasSuffix:@"next"]) {
113                 battleCell = nil;
114         }
115         [battle setValue:battleCell forKeyPath:@"battleCell"];
116 }
117
118 - (void)nextCell
119 {
120         NSError *error = nil;
121         NSArray *battles = [self.store objectsWithEntityName:@"Battle"
122                                                                                            predicate:nil
123                                                                                                    error:&error];
124         if(error) {
125                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
126         }
127         if(battles.count == 0) {
128                 NSLog(@"Battle is invalid.");
129                 return;
130         }
131         id battle = battles[0];
132         
133         [battle setValue:@([[self.json valueForKeyPath:@"api_data.api_no"] integerValue]) forKeyPath:@"no"];
134         
135         [self.store saveAction:nil];
136 }
137
138 - (NSMutableArray *)damages
139 {
140         NSManagedObjectContext *moc = self.store.managedObjectContext;
141         
142         NSError *error = nil;
143         NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"id" ascending:YES];
144         NSArray *array = [self.store objectsWithEntityName:@"Damage"
145                                                                            sortDescriptors:@[sortDescriptor]
146                                                                                          predicate:nil
147                                                                                                  error:&error];
148         if(error) {
149                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
150         }
151         // TODO: error handling
152         
153         NSInteger frendShipCount = 12;
154         if(array.count != frendShipCount) {
155                 // Battleエンティティ取得
156                 error = nil;
157                 NSArray *battles = [self.store objectsWithEntityName:@"Battle"
158                                                                                                    predicate:nil
159                                                                                                            error:&error];
160                 if(error) {
161                         [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
162                 }
163                 if(battles.count == 0) {
164                         NSLog(@"Battle is invalid.");
165                         return [NSMutableArray new];
166                 }
167                 id battle = battles[0];
168                 
169                 // Damage エンティティ作成6個
170                 NSMutableArray *damages = [NSMutableArray new];
171                 for(NSInteger i = 0; i < frendShipCount; i++) {
172                         id damage = [NSEntityDescription insertNewObjectForEntityForName:@"Damage"
173                                                                                                           inManagedObjectContext:moc];
174                         [damage setValue:battle forKeyPath:@"battle"];
175                         [damage setValue:@(i) forKeyPath:@"id"];
176                         [damages addObject:damage];
177                 }
178                 array = damages;
179         }
180         
181         return [NSMutableArray arrayWithArray:array];
182 }
183
184 - (void)calculateHougeki:(NSMutableArray *)damages targetsKeyPath:(NSString *)targetKeyPath damageKeyPath:(NSString *)damageKeyPath
185 {
186 #if DAMAGE_CHECK
187         NSLog(@"Start Hougeki %@", targetKeyPath);
188 #endif
189         id targetShips = [self.json valueForKeyPath:targetKeyPath];
190         if(!targetShips || [targetShips isKindOfClass:[NSNull class]]) return;
191         
192         id hougeki1Damages = [self.json valueForKeyPath:damageKeyPath];
193         NSInteger i = 0;
194         NSInteger offset = self.calcSecondFleet ? 6 : 0;
195         for(NSArray *array in targetShips) {
196                 if(![array isKindOfClass:[NSArray class]]) {
197                         i++;
198                         continue;
199                 }
200                 
201                 NSInteger j = 0;
202                 for(id ship in array) {
203                         NSInteger target = [ship integerValue];
204 #if DAMAGE_CHECK
205                         NSLog(@"Hougeki target -> %ld", target + offset);
206 #endif
207                         if(target < 0 || target > 6) {
208                                 j++;
209                                 continue;
210                         }
211                         
212                         id damageObject = [damages objectAtIndex:target - 1 + offset];
213                         NSInteger damage = [[[hougeki1Damages objectAtIndex:i] objectAtIndex:j] integerValue];
214                         damage += [[damageObject valueForKey:@"damage"] integerValue];
215                         [damageObject setValue:@(damage) forKeyPath:@"damage"];
216                         
217 #if DAMAGE_CHECK
218                         NSLog(@"Hougeki %ld -> %ld", target + offset, damage);
219 #endif
220                         
221                         j++;
222                 }
223                 i++;
224         }
225 }
226
227 - (void)calculateFDam:(NSMutableArray *)damages fdamKeyPath:(NSString *)fdamKeyPath
228 {
229 #if DAMAGE_CHECK
230         NSLog(@"Start FDam %@", fdamKeyPath);
231 #endif
232         id koukuDamage = [self.json valueForKeyPath:fdamKeyPath];
233         if(!koukuDamage || [koukuDamage isEqual:[NSNull null]]) return;
234         
235         NSInteger offset = self.calcSecondFleet ? 6 : 0;
236         for(NSInteger i = 1; i <= 6; i++) {
237                 id damageObject = [damages objectAtIndex:i - 1 + offset];
238                 NSInteger damage = [[koukuDamage objectAtIndex:i] integerValue];
239                 damage += [[damageObject valueForKey:@"damage"] integerValue];
240                 [damageObject setValue:@(damage) forKeyPath:@"damage"];
241                 
242 #if DAMAGE_CHECK
243                 NSLog(@"FDam %ld -> %ld", i + offset, damage);
244 #endif
245         }
246 }
247
248 - (BOOL)isCombinedBattle
249 {
250         return [self.api hasPrefix:@"/kcsapi/api_req_combined_battle"];
251 }
252
253 - (void)calculateBattle
254 {
255         [self updateBattleCell];
256         
257         // 艦隊のチェック
258         
259         // Damage エンティティ作成6個
260         NSMutableArray *damages = [self damages];
261         
262         // koukuu
263         [self calculateFDam:damages
264                         fdamKeyPath:@"api_data.api_kouku.api_stage3.api_fdam"];
265         
266         if(self.isCombinedBattle) {
267                 [self calculateFDam:damages
268                                 fdamKeyPath:@"api_data.api_kouku2.api_stage3.api_fdam"];
269                 
270                 self.calcSecondFleet = YES;
271                 [self calculateFDam:damages
272                                 fdamKeyPath:@"api_data.api_kouku.api_stage3_combined.api_fdam"];
273                 [self calculateFDam:damages
274                                 fdamKeyPath:@"api_data.api_kouku2.api_stage3_combined.api_fdam"];
275                 self.calcSecondFleet = NO;
276         } else {
277                 [self calculateFDam:damages
278                                 fdamKeyPath:@"api_data.api_kouku2.api_stage3.api_fdam"];
279         }
280         
281         // opening attack
282         self.calcSecondFleet = self.isCombinedBattle;
283         [self calculateFDam:damages
284                         fdamKeyPath:@"api_data.api_opening_atack.api_fdam"];
285         self.calcSecondFleet = NO;
286         
287         // hougeki1
288         self.calcSecondFleet = self.isCombinedBattle && self.battleType == typeCombinedAir;
289         [self calculateHougeki:damages
290                         targetsKeyPath:@"api_data.api_hougeki1.api_df_list"
291                          damageKeyPath:@"api_data.api_hougeki1.api_damage"];
292         self.calcSecondFleet = NO;
293         
294         // hougeki2
295         [self calculateHougeki:damages
296                         targetsKeyPath:@"api_data.api_hougeki2.api_df_list"
297                          damageKeyPath:@"api_data.api_hougeki2.api_damage"];
298         
299         // hougeki3
300         self.calcSecondFleet = self.isCombinedBattle && self.battleType == typeCombinedWater;
301         [self calculateHougeki:damages
302                         targetsKeyPath:@"api_data.api_hougeki3.api_df_list"
303                          damageKeyPath:@"api_data.api_hougeki3.api_damage"];
304         self.calcSecondFleet = NO;
305
306         // raigeki
307         self.calcSecondFleet = self.isCombinedBattle;
308         [self calculateFDam:damages
309                         fdamKeyPath:@"api_data.api_raigeki.api_fdam"];
310         self.calcSecondFleet = NO;
311         
312         [self.store saveAction:nil];
313 }
314
315 - (void)calculateMidnightBattle
316 {
317         [self updateBattleCell];
318         
319         // Damage 取得
320         NSMutableArray *damages = [self damages];
321         
322         // hougeki
323         self.calcSecondFleet = self.isCombinedBattle;
324         [self calculateHougeki:damages
325                         targetsKeyPath:@"api_data.api_hougeki.api_df_list"
326                          damageKeyPath:@"api_data.api_hougeki.api_damage"];
327         self.calcSecondFleet = NO;
328         
329         [self.store saveAction:nil];
330 }
331
332 - (NSArray *)deckWithNumber:(NSNumber *)number
333 {
334         return [NSArray array];
335 }
336 - (void)applyDamage
337 {
338         // Damage 取得
339         NSArray *damages = nil;
340         
341         NSError *error = nil;
342         NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"id" ascending:YES];
343         damages = [self.store objectsWithEntityName:@"Damage"
344                                                                 sortDescriptors:@[sortDescriptor]
345                                                                           predicate:nil
346                                                                                   error:&error];
347         if(error) {
348                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
349                 return;
350         }
351         
352         if(damages.count != 12) {
353                 [self log:@"Damage is invalid. count %lx", damages.count];
354                 return;
355         }
356         
357         error = nil;
358         NSArray *array = [self.store objectsWithEntityName:@"Battle"
359                                                                                 predicate:nil
360                                                                                         error:&error];
361         if(error) {
362                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
363                 return;
364         }
365         if(array.count == 0) {
366                 [self log:@"Battle is invalid. %s", __PRETTY_FUNCTION__];
367                 return;
368         }
369         
370         HMServerDataStore *serverStore = [HMServerDataStore oneTimeEditor];
371         NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id = %@", [array[0] valueForKey:@"deckId"]];
372         BOOL firstRun = YES;
373         for(NSInteger i = 0; i < 2; i++) {
374                 // 艦隊メンバーを取得
375                 error = nil;
376                 NSArray *decks = [serverStore objectsWithEntityName:@"Deck"
377                                                                                                   predicate:predicate
378                                                                                                           error:&error];
379                 if(error) {
380                         [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
381                         return;
382                 }
383                 
384                 if(decks.count == 0) {
385                         [self log:@"Deck is invalid. %s", __PRETTY_FUNCTION__];
386                         return;
387                 }
388                 id deck = decks[0];
389                 NSMutableArray *shipIds = [NSMutableArray new];
390                 [shipIds addObject:[deck valueForKey:@"ship_0"]];
391                 [shipIds addObject:[deck valueForKey:@"ship_1"]];
392                 [shipIds addObject:[deck valueForKey:@"ship_2"]];
393                 [shipIds addObject:[deck valueForKey:@"ship_3"]];
394                 [shipIds addObject:[deck valueForKey:@"ship_4"]];
395                 [shipIds addObject:[deck valueForKey:@"ship_5"]];
396                 
397                 NSMutableArray *ships = [NSMutableArray new];
398                 for(id shipId in shipIds) {
399                         error = nil;
400                         NSArray *ship = [serverStore objectsWithEntityName:@"Ship"
401                                                                                                                  error:&error
402                                                                                            predicateFormat:@"id = %@", @([shipId integerValue])];
403                         if(error) {
404                                 [self log:@"%s error: %@", __PRETTY_FUNCTION__, error];
405                         }
406                         if(ship.count != 0 && ![ship[0] isEqual:[NSNull null]]) {
407                                 [ships addObject:ship[0]];
408                         }
409                 }
410                 
411                 NSUInteger shipCount = ships.count;
412                 NSUInteger offset = (self.isCombinedBattle && !firstRun) ? 6 : 0;
413                 for(NSInteger i = 0; i < shipCount; i++) {
414                         id ship = ships[i];
415                         NSInteger damage = [[damages[i + offset] valueForKey:@"damage"] integerValue];
416                         NSInteger nowhp = [[ship valueForKey:@"nowhp"] integerValue];
417                         nowhp -= damage;
418                         [ship setValue:@(nowhp) forKeyPath:@"nowhp"];
419                 }
420                 
421                 predicate = [NSPredicate predicateWithFormat:@"id = %@", @2];
422                 firstRun = NO;
423                 
424                 if(!self.isCombinedBattle) break;
425         }
426         
427         [serverStore saveAction:nil];
428 }
429
430 - (void)execute
431 {
432         if([self.api isEqualToString:@"/kcsapi/api_req_map/start"]) {
433                 [self resetBattle];
434                 [self startBattle];
435                 return;
436         }
437         if([self.api isEqualToString:@"/kcsapi/api_req_map/next"]) {
438                 [self nextCell];
439                 [self updateBattleCell];
440                 return;
441         }
442         
443         if([self.api isEqualToString:@"/kcsapi/api_req_sortie/battle"]) {
444                 [self calculateBattle];
445                 return;
446         }
447         if([self.api isEqualToString:@"/kcsapi/api_req_sortie/airbattle"]) {
448                 [self calculateBattle];
449                 return;
450         }
451         if([self.api isEqualToString:@"/kcsapi/api_req_battle_midnight/battle"]
452            || [self.api isEqualToString:@"/kcsapi/api_req_battle_midnight/sp_midnight"]) {
453                 [self calculateMidnightBattle];
454                 return;
455         }
456         
457         /*
458          /kcsapi/api_req_combined_battle/battle_water
459          /kcsapi/api_req_combined_battle/midnight_battle
460          /kcsapi/api_req_combined_battle/battleresult
461          */
462         // combined battle
463         if([self.api isEqualToString:@"/kcsapi/api_req_combined_battle/battle"]
464            || [self.api isEqualToString:@"/kcsapi/api_req_combined_battle/airbattle"]) {
465                 self.battleType = typeCombinedAir;
466                 [self calculateBattle];
467                 return;
468         }
469         if([self.api isEqualToString:@"/kcsapi/api_req_combined_battle/battle_water"]) {
470            self.battleType = typeCombinedWater;
471                 [self calculateBattle];
472                 return;
473         }
474         
475         if([self.api isEqualToString:@"/kcsapi/api_req_combined_battle/midnight_battle"]
476            || [self.api isEqualToString:@"/kcsapi/api_req_combined_battle/sp_midnight"]) {
477                 [self calculateMidnightBattle];
478                 return;
479         }
480         
481         if([self.api isEqualToString:@"/kcsapi/api_req_sortie/battleresult"]
482            || [self.api isEqualToString:@"/kcsapi/api_req_combined_battle/battleresult"]) {
483                 [self applyDamage];
484                 [self resetDamage];
485                 return;
486         }
487         
488         NSLog(@"undefined battle type");
489 }
490
491 @end