Skip to content

Commit

Permalink
feat(items): add gold offset
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveVanOpstal committed Dec 12, 2016
1 parent 0d74e95 commit 5a93c84
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 142 deletions.
43 changes: 1 addition & 42 deletions src/client/build/items/item-slot.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {inject, TestBed} from '@angular/core/testing';
import {TestBed} from '@angular/core/testing';

import {settings} from '../../../../config/settings';
import {LolApiService} from '../../services/lolapi.service';
import {StatsService} from '../../services/stats.service';
import {TestModule} from '../../testing';
Expand All @@ -15,44 +14,4 @@ describe('ItemSlotComponent', () => {
imports: [TestModule]
});
});

let item1;
let item2;

beforeEach(inject([ItemSlotComponent], (component) => {
item1 = {id: 3341, gold: {total: 0}};

item2 = {id: 2003, gold: {total: 50}};

component.samples = {gold: [0, 100, 200, 300]};
component.items = [item1, item2, item2, item2];
}));

it('should add an item', inject([ItemSlotComponent], (component) => {
spyOn(component, 'addTime');
spyOn(component, 'addBundle');
expect(component.addTime).not.toHaveBeenCalled();
expect(component.addBundle).not.toHaveBeenCalled();
component.addItem(item1);
expect(component.addTime).toHaveBeenCalled();
expect(component.addBundle).toHaveBeenCalled();
expect(component.items[4]).toHaveEqualContent(item1);
}));

it('should calculate time', inject([ItemSlotComponent], (component) => {
component.addTime(item1);
expect(item1.time).toBe(0);
component.addTime(item2);
expect(item2.time)
.toBe(
(settings.gameTime / settings.matchServer.sampleSize) / component.samples.gold[1] *
item2.gold.total);
}));

it('should bundle', inject([ItemSlotComponent], (component) => {
component.addTime(item2);
component.addBundle(item2);
expect(component.items.length).toBe(2);
expect(component.items[1].bundle).toBe(3);
}));
});
99 changes: 30 additions & 69 deletions src/client/build/items/item-slot.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {Component, Input, OnInit} from '@angular/core';

import {settings} from '../../../../config/settings';
import {LolApiService} from '../../services/lolapi.service';
import {Item} from '../item';
import {Samples} from '../samples';

@Component({
selector: 'lb-item-slot',
Expand All @@ -18,96 +16,59 @@ import {Samples} from '../samples';

export class ItemSlotComponent implements OnInit {
@Input() id: number;
private samples: Samples;
private items: Array<Item> = new Array<Item>();
items = Array<Item>();

private allItems;

constructor(private lolApi: LolApiService) {}

ngOnInit() {
this.lolApi.getCurrentMatchData().subscribe(samples => {
this.samples = samples;
this.lolApi.getItems().subscribe(res => {
this.allItems = res.data;
});
}

addItem(item: Item) {
this.addTime(item);
this.addBundle(item);
this.items.push(item);
}

removeItem(item: Item) {
this.items.splice(this.items.indexOf(item), 1);
}

getItems(): Array<Item> {
return this.items;
}

compatible(item: Item) {
if (!this.items.length) {
return true;
}
let from = this.items[this.items.length - 1].from;
if (!from) {
return true;
}
return from.indexOf(item.id.toString()) > -1;
let item2 = this.items[this.items.length - 1];
return this.buildsFrom(item, item2);
}

// TODO: move to itemComponent when angular allows events on <template>
rightClicked(item: Item) {
this.removeItem(item);
// this.removeItem(item);
return false; // stop context menu from appearing
}

private addTime(item: Item) {
if (this.samples) {
item.time = this.getTime(
this.samples.gold, item.gold.total, settings.gameTime, settings.matchServer.sampleSize);
}
}

private addBundle(item: Item) {
if (!this.items || !this.items.length) {
return;
private buildsFrom(subject: Item, item: Item) {
let from = subject.from;
if (!from) {
return false;
}

item.bundle = 1;
for (let index = 0; index < this.items.length - 1; index++) {
if (item.id === this.items[index].id && item.time === this.items[index].time) {
item.bundle++;
this.items.splice(index + 1, 1);
index--;
for (let i of from) {
if (this.buildsFrom(this.allItems[i], item)) {
return true;
}
}
}

private getTime(frames: Array<number>, value: number, totalTime: number, sampleSize: number) {
let index = this.getUpperIndex(frames, value);
if (index <= -1) {
return -1;
}

let lowerFrame = frames[index];
let upperFrame = frames[index + 1];

let ratio = (value - lowerFrame) / (upperFrame - lowerFrame);

let sampleTime = totalTime / sampleSize;
let lowerTime = index * sampleTime;
let upperTime = (index + 1) * sampleTime;

let time = lowerTime + ((upperTime - lowerTime) * ratio);
time = isFinite(time) ? time : lowerTime;
return time > 0 ? time : 0;
return from.indexOf(item.id.toString()) > -1;
}

private getUpperIndex(frames: Array<number>, gold: number) {
for (let j = 0; j < frames.length; j++) {
if (frames[j] > gold) {
return j;
}
}
return -1;
}
// private addBundle(item: Item) {
// if (!this.items || !this.items.length) {
// return;
// }

// item.bundle = 1;
// for (let index = 0; index < this.items.length - 1; index++) {
// if (item.id === this.items[index].id && item.time === this.items[index].time) {
// item.bundle++;
// this.items.splice(index + 1, 1);
// index--;
// }
// }
// }
}
17 changes: 2 additions & 15 deletions src/client/build/items/items.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import {inject, TestBed} from '@angular/core/testing';

import {StatsService} from '../../services/stats.service';
import {ItemsComponent} from './items.component';

// class MockItemSlotComponent implements ItemSlotComponent {

// }

describe('ItemsComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({providers: [ItemsComponent]});
TestBed.configureTestingModule({providers: [ItemsComponent, StatsService]});
});

beforeEach(inject([ItemsComponent], (component) => {
Expand All @@ -18,14 +15,4 @@ describe('ItemsComponent', () => {
{'id': 2003, 'gold': {'total': 50}}, {'id': 2003, 'gold': {'total': 50}}
];
}));

// it('should add item', inject([ItemsComponent], (component) => {
// spyOn(component, 'addTime');
// spyOn(component, 'addBundle');
// expect(component.addTime).not.toHaveBeenCalled();
// expect(component.addBundle).not.toHaveBeenCalled();
// component.ngDoCheck();
// expect(component.addTime).toHaveBeenCalled();
// expect(component.addBundle).toHaveBeenCalled();
// }));
});
120 changes: 104 additions & 16 deletions src/client/build/items/items.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import {Component, QueryList, ViewChildren} from '@angular/core';
import {Component, OnInit, QueryList, ViewChildren} from '@angular/core';

import {settings} from '../../../../config/settings';
import {LolApiService} from '../../services/lolapi.service';
import {StatsService} from '../../services/stats.service';
import {Item} from '../item';
import {Samples} from '../samples';

import {ItemSlotComponent} from './item-slot.component';

export interface SlotItem {
item: Item;
slotId: number;
}

@Component({
selector: 'lb-items',
template: `
Expand All @@ -16,35 +24,115 @@ import {ItemSlotComponent} from './item-slot.component';
<lb-item-slot [id]="5"></lb-item-slot>`
})

export class ItemsComponent {
export class ItemsComponent implements OnInit {
@ViewChildren(ItemSlotComponent) children: QueryList<ItemSlotComponent>;
private samples: Samples;
private slotItems: Array<SlotItem> = new Array<SlotItem>();

constructor(private stats: StatsService) {}
constructor(private stats: StatsService, private lolApi: LolApiService) {}

addItemSlotComponent(slot: ItemSlotComponent) {
this.children.toArray()[slot.id] = slot;
ngOnInit() {
this.lolApi.getCurrentMatchData().subscribe(samples => {
this.samples = samples;
});
}

addItem(item: Item) {
this.addToFirstCompatibleSlot(item);
let slotId = this.findSlot(item);
let slotItem = {item, slotId};
this.slotItems.push(slotItem);
this.addTime(slotItem);
this.update();
}

private addToFirstCompatibleSlot(item: Item) {
let s;
this.children.toArray().forEach((slot: ItemSlotComponent) => {
if (slot.compatible(item) && !s) {
s = slot;
private addTime(slotItem: SlotItem) {
if (this.samples) {
let goldOffset = this.getGoldOffset(slotItem);
slotItem.item.time = this.getTime(
this.samples.gold, goldOffset + slotItem.item.gold.total, settings.gameTime,
settings.matchServer.sampleSize);
}
}

private getGoldOffset(input: SlotItem): number {
let gold = 0;
for (let slotItem of this.slotItems) {
if (slotItem === input) {
break;
} else {
gold += slotItem.item.gold.total;
}
}
return gold;
}

private getTime(frames: Array<number>, value: number, totalTime: number, sampleSize: number):
number {
let index = this.getUpperIndex(frames, value);
if (index <= -1) {
return -1;
}

let lowerFrame = frames[index];
let upperFrame = frames[index + 1];

let ratio = (value - lowerFrame) / (upperFrame - lowerFrame);

let sampleTime = totalTime / sampleSize;
let lowerTime = index * sampleTime;
let upperTime = (index + 1) * sampleTime;

let time = lowerTime + ((upperTime - lowerTime) * ratio);
time = isFinite(time) ? time : lowerTime;
return time > 0 ? time : 0;
}

private getUpperIndex(frames: Array<number>, gold: number): number {
for (let j = 0; j < frames.length; j++) {
if (frames[j] > gold) {
return j;
}
}
return -1;
}

private findSlot(item: Item): number {
let s = this.children.toArray().find((slot: ItemSlotComponent) => {
return slot.compatible(item);
});
s.addItem(item);
if (s) {
return s.id;
}
}

private update() {
this.updateItemSlots();
this.updatePickedItems();
}

private updateItemSlots() {
this.children.toArray().forEach((slot: ItemSlotComponent) => {
slot.items = this.getItemsForSlot(slot.id);
});
}

private updatePickedItems() {
let pickedItems = [];
this.children.toArray().forEach((itemSlot) => {
pickedItems = pickedItems.concat(itemSlot.getItems());
this.stats.pickedItems.next(this.getItems());
}

private getItems(): Array<Item> {
return this.slotItems.map((slotItem: SlotItem) => {
return slotItem.item;
});
this.stats.pickedItems.next(pickedItems);
}

private getItemsForSlot(slotId: number): Array<Item> {
return this.slotItems
.filter((slotItem: SlotItem) => {
return slotItem.slotId === slotId;
})
.map((slotItem: SlotItem) => {
return slotItem.item;
});
}
}

0 comments on commit 5a93c84

Please sign in to comment.