Solution: Both Challenges

JSStockHolding.h

[code]@property (nonatomic, copy) NSString *companyName;
@property (nonatomic) int numberShares;
@property (nonatomic) float purchaseSharePrice;
@property (nonatomic) float currentSharePrice;

  • (float)costDollars; // purchaseSharePrice * numberShares
  • (float)valueDollars; // currentSharePrice * numberShares[/code]

JSStockHolding.m

[code]- (float)costDollars
{
return self.purchaseSharePrice * self.numberShares;
}

  • (float)valueDollars
    {
    return self.currentSharePrice * self.numberShares;
    }

  • (NSString *)description
    {
    NSString *descriptionMethod = [NSString stringWithFormat:@“You paid %.2f for %d shares in %@, now valued at %.2f”, self.costDollars, self.numberShares, self.companyName, self.valueDollars];
    return descriptionMethod;
    }[/code]

JSForeignStockHolding.h

[code]@property (nonatomic) float conversionRate;

  • (float)selectRate:(int)index;[/code]

JSForeignStockHolding.m

[code]- (float)selectRate:(int)index
{
float selectRate;
switch (index) {
case 0:
selectRate = 6.21; // USD --> German Mark
break;
case 1:
selectRate = 0.89; // USD --> European Euro
break;
case 2:
selectRate = 1.74; // USD --> Chinese Yuan
break;
case 3:
selectRate = 0.93; // USD --> Swiss Franc
break;
default:
selectRate = 1.0;
break;
}
return selectRate;
}

  • (float)costDollars
    {
    return self.purchaseSharePrice * self.numberShares * self.conversionRate;
    }

  • (float)valueDollars
    {
    return self.currentSharePrice * self.numberShares * self.conversionRate;
    }

  • (NSString *)description
    {
    NSString *descriptionMethod = [NSString stringWithFormat:@“You paid %.2f for %d shares in %@ (CVR: %.2f), now valued at %.2f.”, self.costDollars, self.numberShares, self.companyName, self.conversionRate, self.valueDollars];
    return descriptionMethod;
    }[/code]

JSPortfolio.h

[code]@property (nonatomic, copy) NSArray *stocks;

  • (void)addStock:(JSStockHolding *)stock;

  • (void)removeStock:(JSStockHolding *)stock withName:(NSString *)name;

  • (float)portfolioValue;

  • (float)totalCost;

  • (NSArray *)topThreeStockValues;

  • (NSArray *)sortByName;[/code]

JSPortfolio.m

[code]@interface JSPortfolio()

{
NSMutableArray *_stocks;
}

@end

@implementation JSPortfolio

  • (void)setPortfolio:(NSArray *)portfolio
    {
    _stocks = [portfolio mutableCopy];
    }

  • (NSArray *)stocks
    {
    return [_stocks mutableCopy];
    }

  • (void)addStock:(JSStockHolding *)stock
    {
    // if (portfolio array does not exist)
    if (!_stocks) {
    _stocks = [[NSMutableArray alloc] init];
    }
    [_stocks addObject:stock];
    }

  • (void)removeStock:(JSStockHolding *)stock withName:(NSString *)name
    {
    for (int i = 0; i < [self.stocks count]; i++) {
    if (stock.companyName == name) {
    [_stocks removeObject:stock];
    // Log for clarity purposes
    NSLog(@“Removing %@ from portfolio.\n”, stock.companyName);
    break; // End loop once name found
    }
    }
    }

  • (float)portfolioValue
    {
    float sum = 0;
    for (JSStockHolding *stock in _stocks) {
    sum += [stock valueDollars];
    }
    return sum;
    }

  • (float)totalCost
    {
    float sum = 0;
    for (JSStockHolding *stock in _stocks) {
    sum += [stock costDollars];
    }
    return sum;
    }

  • (NSArray *)topThreeStockValues
    {
    NSSortDescriptor *descriptors = [NSSortDescriptor sortDescriptorWithKey:@"valueDollars"
    ascending:NO];
    NSArray *sortedStocks = [_stocks sortedArrayUsingDescriptors:@[descriptors]];
    NSIndexSet *selectedStocks = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 3)];
    return [sortedStocks objectsAtIndexes:selectedStocks];
    }

  • (NSArray *)sortByName
    {
    NSSortDescriptor *descriptors = [NSSortDescriptor sortDescriptorWithKey:@"companyName"
    ascending:YES];
    NSArray *sortedStocks = [_stocks sortedArrayUsingDescriptors:@[descriptors]];
    return sortedStocks;
    }

  • (NSString *)description
    {
    NSString *descriptionMethod = [NSString stringWithFormat:@“Portfolio Contents:\n%@\nAnalysis: Your portfolio cost %.2f and is valued at %.2f.”, self.stocks, self.totalCost, self.portfolioValue];
    return descriptionMethod;
    }

@end[/code]

Main.m

[code]JSPortfolio *portfolio = [[JSPortfolio alloc] init];

JSStockHolding *localStock;
JSForeignStockHolding *foreignStock;

// Used in two for-loops, made sense to declare outside
float randomPurchasePrice;
float randomSharePrice;
int randomNumberShares;

// Names - local & foreign stock objects
NSArray *localNames = @[@“APPLE”, @“CHRYSLER”, @“MICROSOFT”, @“NETFLIX”];
NSArray *foreignNames = @[@“IZUZU”, @“TOYOTA”, @“TOSHIBA”, @“FUJITSU”];

// Create 4 stockholding objects
for (int i = 0; i < [localNames count]; i++) {
// ---- “JSStockHolding” object ----
localStock = [[JSStockHolding alloc] init];

//  Used in place of "stockTicker" symbol from book
localStock.companyName = [localNames objectAtIndex:i];


//  Dont worry about the math, just playing with creating random numbers
randomPurchasePrice = 2.30 + i * (arc4random() % 3);
randomSharePrice = 4.50 + i * (arc4random() % 2);
randomNumberShares = (i + 1) * (arc4random() % 25);

localStock.purchaseSharePrice = randomPurchasePrice;
localStock.currentSharePrice = randomSharePrice;
localStock.numberShares = randomNumberShares;

[portfolio addStock:localStock];  //  Add "stockholding" object to portfolio

}

// Create 4 foreign stockholding objects
for (int i = 0; i < [foreignNames count]; i++) {
// ---- “JSForeignStockHolding” object ----
foreignStock = [[JSForeignStockHolding alloc] init];

//  Used in place of "stockTicker" symbol from book
foreignStock.companyName = [foreignNames objectAtIndex:i];

foreignStock.conversionRate = [foreignStock selectRate:i];

//  Dont worry about the math, just playing with creating random numbers
randomPurchasePrice = 2.30 + i * (arc4random() % 3);
randomSharePrice = 4.50 + i * (arc4random() % 2);
randomNumberShares = (i + 1) * (arc4random() % 25);

foreignStock.purchaseSharePrice = randomPurchasePrice;
foreignStock.currentSharePrice = randomSharePrice;
foreignStock.numberShares = randomNumberShares;

[portfolio addStock:foreignStock];  //  Add "foreignStockHolding" object to portfolio

}

NSLog(@“Initial Assessment: %.2f Expenditure / %.2f Value:\n”, portfolio.totalCost, portfolio.portfolioValue);
NSLog(@"%@\n\n", portfolio.sortByName);
NSLog(@“Top Three Stocks:\n%@”, portfolio.topThreeStockValues);[/code]

Output

[quote]Initial Assessment: $2117.03 Expenditure / $2487.02 Value:
(
“You paid $52.90 for 23 shares in APPLE, now valued at $103.50”,
“You paid $68.80 for 16 shares in CHRYSLER, now valued at $88.00”,
“You paid $136.90 for 64 shares in FUJITSU (CVR: 0.93), now valued at $446.40.”,
“You paid $128.55 for 9 shares in IZUZU (CVR: 6.21), now valued at $251.51.”,
“You paid $434.70 for 69 shares in MICROSOFT, now valued at $310.50”,
“You paid $424.00 for 80 shares in NETFLIX, now valued at $600.00”,
“You paid $756.38 for 69 shares in TOSHIBA (CVR: 1.74), now valued at $540.27.”,
“You paid $114.81 for 30 shares in TOYOTA (CVR: 0.89), now valued at $146.85.”
)

Top Three Stocks:
(
“You paid $424.00 for 80 shares in NETFLIX, now valued at $600.00”,
“You paid $756.38 for 69 shares in TOSHIBA (CVR: 1.74), now valued at $540.27.”,
“You paid $136.90 for 64 shares in FUJITSU (CVR: 0.93), now valued at $446.40.”
)[/quote]