Line data Source code
1 0 : /*
2 :
3 : OOCommodityMarket.m
4 :
5 : Oolite
6 : Copyright (C) 2004-2014 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 : #import "OOCommodities.h"
26 : #import "OOCommodityMarket.h"
27 : #import "OOCollectionExtractors.h"
28 : #import "OOStringExpander.h"
29 :
30 :
31 : static NSComparisonResult goodsSorter(id a, id b, void *context);
32 :
33 :
34 : @implementation OOCommodityMarket
35 :
36 0 : - (id) init
37 : {
38 : self = [super init];
39 : if (self == nil) return nil;
40 :
41 : _commodityList = [[NSMutableDictionary dictionaryWithCapacity:24] retain];
42 :
43 : _sortedKeys = nil;
44 :
45 : return self;
46 : }
47 :
48 :
49 0 : - (void) dealloc
50 : {
51 : DESTROY(_commodityList);
52 : DESTROY(_sortedKeys);
53 : [super dealloc];
54 : }
55 :
56 :
57 : - (NSUInteger) count
58 : {
59 : return [_commodityList count];
60 : }
61 :
62 :
63 : - (void) setGood:(OOCommodityType)key withInfo:(NSDictionary *)info
64 : {
65 : NSMutableDictionary *definition = [NSMutableDictionary dictionaryWithDictionary:info];
66 : [_commodityList setObject:definition forKey:key];
67 : DESTROY(_sortedKeys); // reset
68 : }
69 :
70 :
71 : - (NSArray *) goods
72 : {
73 : if (_sortedKeys == nil)
74 : {
75 : NSArray *keys = [_commodityList allKeys];
76 : _sortedKeys = [[keys sortedArrayUsingFunction:goodsSorter context:_commodityList] retain];
77 : }
78 : return _sortedKeys;
79 : }
80 :
81 :
82 : - (NSDictionary *) dictionaryForScripting
83 : {
84 : return [[_commodityList copy] autorelease];
85 : }
86 :
87 :
88 : - (BOOL) setPrice:(OOCreditsQuantity)price forGood:(OOCommodityType)good
89 : {
90 : NSMutableDictionary *definition = [_commodityList oo_mutableDictionaryForKey:good];
91 : if (definition == nil)
92 : {
93 : return NO;
94 : }
95 : [definition oo_setUnsignedInteger:price forKey:kOOCommodityPriceCurrent];
96 : return YES;
97 : }
98 :
99 :
100 : - (BOOL) setQuantity:(OOCargoQuantity)quantity forGood:(OOCommodityType)good
101 : {
102 : NSMutableDictionary *definition = [_commodityList oo_mutableDictionaryForKey:good];
103 : if (definition == nil || quantity > [self capacityForGood:good])
104 : {
105 : return NO;
106 : }
107 : [definition oo_setUnsignedInteger:quantity forKey:kOOCommodityQuantityCurrent];
108 : return YES;
109 : }
110 :
111 :
112 : - (BOOL) addQuantity:(OOCargoQuantity)quantity forGood:(OOCommodityType)good
113 : {
114 : OOCargoQuantity current = [self quantityForGood:good];
115 : if (current + quantity > [self capacityForGood:good])
116 : {
117 : return NO;
118 : }
119 : [self setQuantity:(current+quantity) forGood:good];
120 : return YES;
121 : }
122 :
123 :
124 : - (BOOL) removeQuantity:(OOCargoQuantity)quantity forGood:(OOCommodityType)good
125 : {
126 : OOCargoQuantity current = [self quantityForGood:good];
127 : if (current < quantity)
128 : {
129 : return NO;
130 : }
131 : [self setQuantity:(current-quantity) forGood:good];
132 : return YES;
133 : }
134 :
135 :
136 : - (void) removeAllGoods
137 : {
138 : OOCommodityType good = nil;
139 : foreach (good, [_commodityList allKeys])
140 : {
141 : [self setQuantity:0 forGood:good];
142 : }
143 : }
144 :
145 :
146 : - (BOOL) setComment:(NSString *)comment forGood:(OOCommodityType)good
147 : {
148 : NSMutableDictionary *definition = [_commodityList oo_mutableDictionaryForKey:good];
149 : if (definition == nil)
150 : {
151 : return NO;
152 : }
153 : [definition setObject:comment forKey:kOOCommodityComment];
154 : return YES;
155 : }
156 :
157 :
158 : - (BOOL) setShortComment:(NSString *)comment forGood:(OOCommodityType)good
159 : {
160 : NSMutableDictionary *definition = [_commodityList oo_mutableDictionaryForKey:good];
161 : if (definition == nil)
162 : {
163 : return NO;
164 : }
165 : [definition setObject:comment forKey:kOOCommodityShortComment];
166 : return YES;
167 : }
168 :
169 :
170 : - (NSString *) nameForGood:(OOCommodityType)good
171 : {
172 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
173 : if (definition == nil)
174 : {
175 : return OOExpand(@"[oolite-unknown-commodity-name]");
176 : }
177 : return OOExpand([definition oo_stringForKey:kOOCommodityName defaultValue:@"[oolite-unknown-commodity-name]"]);
178 : }
179 :
180 :
181 : - (NSString *) commentForGood:(OOCommodityType)good
182 : {
183 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
184 : if (definition == nil)
185 : {
186 : return OOExpand(@"[oolite-unknown-commodity-name]");
187 : }
188 : return OOExpand([definition oo_stringForKey:kOOCommodityComment defaultValue:@"[oolite-commodity-no-comment]"]);
189 : }
190 :
191 :
192 : - (NSString *) shortCommentForGood:(OOCommodityType)good
193 : {
194 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
195 : if (definition == nil)
196 : {
197 : return OOExpand(@"[oolite-unknown-commodity-name]");
198 : }
199 : return OOExpand([definition oo_stringForKey:kOOCommodityShortComment defaultValue:@"[oolite-commodity-no-short-comment]"]);
200 : }
201 :
202 :
203 : - (OOCreditsQuantity) priceForGood:(OOCommodityType)good
204 : {
205 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
206 : if (definition == nil)
207 : {
208 : return 0;
209 : }
210 : return [definition oo_unsignedIntegerForKey:kOOCommodityPriceCurrent];
211 : }
212 :
213 :
214 : - (OOCargoQuantity) quantityForGood:(OOCommodityType)good
215 : {
216 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
217 : if (definition == nil)
218 : {
219 : return 0;
220 : }
221 : return [definition oo_unsignedIntForKey:kOOCommodityQuantityCurrent];
222 : }
223 :
224 :
225 : - (OOMassUnit) massUnitForGood:(OOCommodityType)good
226 : {
227 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
228 : if (definition == nil)
229 : {
230 : return UNITS_TONS;
231 : }
232 : return [definition oo_unsignedIntForKey:kOOCommodityContainer];
233 : }
234 :
235 :
236 : - (NSUInteger) exportLegalityForGood:(OOCommodityType)good
237 : {
238 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
239 : if (definition == nil)
240 : {
241 : return 0;
242 : }
243 : return [definition oo_unsignedIntegerForKey:kOOCommodityLegalityExport];
244 : }
245 :
246 :
247 : - (NSUInteger) importLegalityForGood:(OOCommodityType)good
248 : {
249 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
250 : if (definition == nil)
251 : {
252 : return 0;
253 : }
254 : return [definition oo_unsignedIntegerForKey:kOOCommodityLegalityImport];
255 : }
256 :
257 :
258 : - (OOCargoQuantity) capacityForGood:(OOCommodityType)good
259 : {
260 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
261 : if (definition == nil)
262 : {
263 : return 0;
264 : }
265 : // should only be undefined for main system markets, not secondary stations
266 : // meaningless for player ship, though
267 : return [definition oo_unsignedIntForKey:kOOCommodityCapacity defaultValue:MAIN_SYSTEM_MARKET_LIMIT];
268 : }
269 :
270 :
271 : - (float) trumbleOpinionForGood:(OOCommodityType)good
272 : {
273 : NSDictionary *definition = [_commodityList oo_dictionaryForKey:good];
274 : if (definition == nil)
275 : {
276 : return 0;
277 : }
278 : return [definition oo_floatForKey:kOOCommodityTrumbleOpinion];
279 : }
280 :
281 :
282 : - (NSDictionary *) definitionForGood:(OOCommodityType)good
283 : {
284 : return [[[_commodityList oo_dictionaryForKey:good] copy] autorelease];
285 : }
286 :
287 :
288 :
289 : - (NSArray *) savePlayerAmounts
290 : {
291 : NSMutableArray *amounts = [NSMutableArray arrayWithCapacity:[self count]];
292 : OOCommodityType good = nil;
293 : foreach (good, [self goods])
294 : {
295 : [amounts addObject:[NSArray arrayWithObjects:good,[NSNumber numberWithUnsignedInt:[self quantityForGood:good]],nil]];
296 : }
297 : return [NSArray arrayWithArray:amounts];
298 : }
299 :
300 :
301 : - (void) loadPlayerAmounts:(NSArray *)amounts
302 : {
303 : OOCargoQuantity q;
304 : BOOL loadedOK;
305 : NSString *good = nil;
306 : foreach (good, [self goods])
307 : {
308 : // make sure that any goods not defined in the save game are zeroed
309 : [self setQuantity:0 forGood:good];
310 : }
311 :
312 :
313 : NSArray *loaded = nil;
314 : foreach (loaded, amounts)
315 : {
316 : loadedOK = NO;
317 : good = [loaded oo_stringAtIndex:0];
318 : q = [loaded oo_unsignedIntAtIndex:1];
319 : // old save games might have more in the array, but we don't care
320 : if (![self setQuantity:q forGood:good])
321 : {
322 : // then it's an array from a 1.80-or-earlier save game and
323 : // the good name is the description string (maybe a
324 : // translated one)
325 : OOCommodityType key = nil;
326 : foreach (key, [self goods])
327 : {
328 : if ([good isEqualToString:[self nameForGood:key]])
329 : {
330 : [self setQuantity:q forGood:key];
331 : loadedOK = YES;
332 : break;
333 : }
334 : }
335 : }
336 : else
337 : {
338 : loadedOK = YES;
339 : }
340 : if (!loadedOK)
341 : {
342 : OOLog(@"setCommanderDataFromDictionary.warning.cargo",@"Cargo %@ (%u units) could not be loaded from the saved game, as it is no longer defined",good,q);
343 : }
344 : }
345 : }
346 :
347 :
348 : - (NSArray *) saveStationAmounts
349 : {
350 : NSMutableArray *amounts = [NSMutableArray arrayWithCapacity:[self count]];
351 : OOCommodityType good = nil;
352 : foreach (good, [self goods])
353 : {
354 : [amounts addObject:[NSArray arrayWithObjects:good,[NSNumber numberWithUnsignedInt:[self quantityForGood:good]],[NSNumber numberWithUnsignedInteger:[self priceForGood:good]],nil]];
355 : }
356 : return [NSArray arrayWithArray:amounts];
357 : }
358 :
359 :
360 : - (void) loadStationAmounts:(NSArray *)amounts
361 : {
362 : OOCargoQuantity q;
363 : OOCreditsQuantity p;
364 : BOOL loadedOK;
365 : NSString *good = nil;
366 :
367 : NSArray *loaded = nil;
368 : foreach (loaded, amounts)
369 : {
370 : loadedOK = NO;
371 : good = [loaded oo_stringAtIndex:0];
372 : q = [loaded oo_unsignedIntAtIndex:1];
373 : p = [loaded oo_unsignedIntegerAtIndex:2];
374 : // old save games might have more in the array, but we don't care
375 : if (![self setQuantity:q forGood:good])
376 : {
377 : // then it's an array from a 1.80-or-earlier save game and
378 : // the good name is the description string (maybe a
379 : // translated one)
380 : OOCommodityType key = nil;
381 : foreach (key, [self goods])
382 : {
383 : if ([good isEqualToString:[self nameForGood:key]])
384 : {
385 : [self setQuantity:q forGood:key];
386 : [self setPrice:p forGood:key];
387 : loadedOK = YES;
388 : break;
389 : }
390 : }
391 : }
392 : else
393 : {
394 : [self setPrice:p forGood:good];
395 : loadedOK = YES;
396 : }
397 : if (!loadedOK)
398 : {
399 : OOLog(@"load.warning.cargo",@"Station market good %@ (%u units) could not be loaded from the saved game, as it is no longer defined",good,q);
400 : }
401 : }
402 : }
403 :
404 :
405 : @end
406 :
407 :
408 0 : static NSComparisonResult goodsSorter(id a, id b, void *context)
409 : {
410 : NSDictionary *commodityList = (NSDictionary *)context;
411 : int v1 = [[commodityList oo_dictionaryForKey:(NSString *)a] oo_intForKey:kOOCommoditySortOrder];
412 : int v2 = [[commodityList oo_dictionaryForKey:(NSString *)b] oo_intForKey:kOOCommoditySortOrder];
413 :
414 : if (v1 < v2)
415 : {
416 : return NSOrderedAscending;
417 : }
418 : else if (v1 > v2)
419 : {
420 : return NSOrderedDescending;
421 : }
422 : else
423 : {
424 : return NSOrderedSame;
425 : }
426 : }
|