Change hero balance action
Target - required by next build resources
This commit is contained in:
		| @@ -1,25 +1,53 @@ | ||||
| import { ActionController, registerAction } from './ActionController'; | ||||
| import { Args } from '../Common'; | ||||
| import { Task } from '../Storage/TaskQueue'; | ||||
| import { grabResources } from '../Page/ResourcesBlock'; | ||||
| import { grabResources, grabResourceStorage } from '../Page/ResourcesBlock'; | ||||
| import { changeHeroResource, grabCurrentHeroResource } from '../Page/HeroPage'; | ||||
| import { HeroAllResources } from '../Game'; | ||||
| import { HeroAllResources, Resources } from '../Game'; | ||||
| import { grabActiveVillageId } from '../Page/VillageBlock'; | ||||
|  | ||||
| @registerAction | ||||
| export class BalanceHeroResourcesAction extends ActionController { | ||||
|     async run(args: Args, task: Task): Promise<any> { | ||||
|         const resourcesAsList = grabResources().asList(); | ||||
|         const resources = this.getRequirements(); | ||||
|  | ||||
|         const resourcesAsList = resources.asList(); | ||||
|         const currentType = grabCurrentHeroResource(); | ||||
|  | ||||
|         const sorted = resourcesAsList.sort((x, y) => x.value - y.value); | ||||
|         const min = sorted[0]; | ||||
|         const max = sorted[sorted.length - 1]; | ||||
|         const delta = max.value - min.value; | ||||
|         const eps = max.value / 10; | ||||
|         const sorted = resourcesAsList.sort((x, y) => y.value - x.value); | ||||
|         const maxRequirement = sorted[0]; | ||||
|         const minRequirement = sorted[sorted.length - 1]; | ||||
|         const delta = maxRequirement.value - minRequirement.value; | ||||
|         const eps = maxRequirement.value / 10; | ||||
|  | ||||
|         const resType = delta > eps ? min.type : HeroAllResources; | ||||
|         const resType = delta > eps ? maxRequirement.type : HeroAllResources; | ||||
|         if (resType !== currentType) { | ||||
|             changeHeroResource(resType); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private getRequirements() { | ||||
|         const resources = grabResources(); | ||||
|  | ||||
|         const villageId = grabActiveVillageId(); | ||||
|         const requiredResources = this.scheduler.getVillageRequiredResources(villageId); | ||||
|  | ||||
|         if (requiredResources) { | ||||
|             return new Resources( | ||||
|                 requiredResources.lumber - resources.lumber, | ||||
|                 requiredResources.clay - resources.clay, | ||||
|                 requiredResources.iron - resources.iron, | ||||
|                 requiredResources.crop - resources.crop | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         const storage = grabResourceStorage(); | ||||
|  | ||||
|         return new Resources( | ||||
|             storage.warehouse - resources.lumber, | ||||
|             storage.warehouse - resources.clay, | ||||
|             storage.warehouse - resources.iron, | ||||
|             storage.granary - resources.crop | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										21
									
								
								src/Action/UpdateBuildingTaskResourcesAction.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/Action/UpdateBuildingTaskResourcesAction.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| import { ActionController, registerAction } from './ActionController'; | ||||
| import { Args } from '../Common'; | ||||
| import { Task } from '../Storage/TaskQueue'; | ||||
| import { grabContractResources } from '../Page/BuildingPage'; | ||||
|  | ||||
| @registerAction | ||||
| export class UpdateBuildingTaskResourcesAction extends ActionController { | ||||
|     async run(args: Args, task: Task): Promise<any> { | ||||
|         const buildingTaskId = args.taskId; | ||||
|         if (buildingTaskId === undefined) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|             const resources = grabContractResources(); | ||||
|             this.scheduler.updateResources(buildingTaskId, resources); | ||||
|         } catch (e) { | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { ResourcesInterface } from './Game'; | ||||
| import { TaskId } from './Storage/TaskQueue'; | ||||
|  | ||||
| export interface Args { | ||||
|     villageId?: number; | ||||
| @@ -6,6 +7,7 @@ export interface Args { | ||||
|     categoryId?: number; | ||||
|     buildTypeId?: number; | ||||
|     resources?: ResourcesInterface; | ||||
|     taskId?: TaskId; | ||||
|     [name: string]: any; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -72,6 +72,7 @@ export class ControlPanel { | ||||
|                     const storage = state.getResourceStorage(); | ||||
|                     const performance = state.getResourcesPerformance(); | ||||
|                     const buildQueueInfo = state.getBuildingQueueInfo(); | ||||
|                     const requiredResources = scheduler.getVillageRequiredResources(village.id); | ||||
|                     return { | ||||
|                         id: village.id, | ||||
|                         name: village.name, | ||||
| @@ -85,6 +86,10 @@ export class ControlPanel { | ||||
|                         clay_hour: performance.clay, | ||||
|                         iron_hour: performance.iron, | ||||
|                         crop_hour: performance.crop, | ||||
|                         lumber_need: requiredResources && requiredResources.lumber, | ||||
|                         clay_need: requiredResources && requiredResources.clay, | ||||
|                         iron_need: requiredResources && requiredResources.iron, | ||||
|                         crop_need: requiredResources && requiredResources.crop, | ||||
|                         warehouse: storage.warehouse, | ||||
|                         granary: storage.granary, | ||||
|                         buildRemainingSeconds: buildQueueInfo.seconds, | ||||
|   | ||||
| @@ -41,12 +41,30 @@ | ||||
|             </td> | ||||
|             <td class="right" v-text="village.granary"></td> | ||||
|           </tr> | ||||
|           <tr class="required-line"> | ||||
|             <td class="right">След:</td> | ||||
|             <td class="right" v-text="village.lumber_need || ''"></td> | ||||
|             <td class="right" v-text="village.clay_need || ''"></td> | ||||
|             <td class="right" v-text="village.iron_need || ''"></td> | ||||
|             <td class="right" v-text="village.crop_need || ''"></td> | ||||
|             <td></td> | ||||
|             <td></td> | ||||
|           </tr> | ||||
|           <tr class="required-line"> | ||||
|             <td class="right">Необх:</td> | ||||
|             <td class="right" v-text="village.lumber_need - village.lumber || ''"></td> | ||||
|             <td class="right" v-text="village.clay_need - village.clay || ''"></td> | ||||
|             <td class="right" v-text="village.iron_need - village.iron || ''"></td> | ||||
|             <td class="right" v-text="village.crop_need - village.crop || ''"></td> | ||||
|             <td></td> | ||||
|             <td></td> | ||||
|           </tr> | ||||
|           <tr class="performance-line"> | ||||
|             <td class="right small" v-text="secondsToTime(village.buildRemainingSeconds)"></td> | ||||
|             <td class="right small">+{{ village.lumber_hour }}</td> | ||||
|             <td class="right small">+{{ village.clay_hour }}</td> | ||||
|             <td class="right small">+{{ village.iron_hour }}</td> | ||||
|             <td class="right small">+{{ village.crop_hour }}</td> | ||||
|             <td class="right" v-text="secondsToTime(village.buildRemainingSeconds)"></td> | ||||
|             <td class="right">+{{ village.lumber_hour }}</td> | ||||
|             <td class="right">+{{ village.clay_hour }}</td> | ||||
|             <td class="right">+{{ village.iron_hour }}</td> | ||||
|             <td class="right">+{{ village.crop_hour }}</td> | ||||
|             <td></td> | ||||
|             <td></td> | ||||
|           </tr> | ||||
| @@ -130,6 +148,12 @@ export default { | ||||
|  | ||||
| .performance-line td { | ||||
|   padding: 0 4px 4px; | ||||
|   font-size: 90%; | ||||
| } | ||||
|  | ||||
| .required-line td { | ||||
|   padding: 0 4px 4px; | ||||
|   font-size: 90%; | ||||
| } | ||||
|  | ||||
| .village-table td.active { | ||||
| @@ -144,10 +168,6 @@ export default { | ||||
|   text-align: right; | ||||
| } | ||||
|  | ||||
| .small { | ||||
|   font-size: 90%; | ||||
| } | ||||
|  | ||||
| .village-quick-link { | ||||
|   display: inline-block; | ||||
| } | ||||
|   | ||||
| @@ -42,6 +42,10 @@ export class Resources implements ResourcesInterface { | ||||
|         this.crop = crop; | ||||
|     } | ||||
|  | ||||
|     static fromObject(obj: ResourcesInterface) { | ||||
|         return new Resources(obj.lumber, obj.clay, obj.iron, obj.crop); | ||||
|     } | ||||
|  | ||||
|     getByType(type: ResourceType): number { | ||||
|         switch (type) { | ||||
|             case ResourceType.Lumber: | ||||
|   | ||||
| @@ -8,6 +8,8 @@ import { ConsoleLogger, Logger } from './Logger'; | ||||
| import { BuildBuildingTask } from './Task/BuildBuildingTask'; | ||||
| import { GrabVillageState } from './Task/GrabVillageState'; | ||||
| import { ActionQueue } from './Storage/ActionQueue'; | ||||
| import { Resources, ResourcesInterface } from './Game'; | ||||
| import { UpdateResourceContracts } from './Task/UpdateResourceContracts'; | ||||
|  | ||||
| export class Scheduler { | ||||
|     private taskQueue: TaskQueue; | ||||
| @@ -20,17 +22,18 @@ export class Scheduler { | ||||
|         this.logger = new ConsoleLogger(this.constructor.name); | ||||
|  | ||||
|         // this.taskQueue.push(GrabVillageState.name, {}, timestamp()); | ||||
|         // this.taskQueue.push(UpdateResourceContracts.name, {}, timestamp()); | ||||
|         // this.taskQueue.push(BalanceHeroResourcesTask.name, {}, timestamp()); | ||||
|  | ||||
|         this.scheduleUniqTask(3600, SendOnAdventureTask.name); | ||||
|         this.scheduleUniqTask(1200, BalanceHeroResourcesTask.name); | ||||
|         this.scheduleUniqTask(180, GrabVillageState.name); | ||||
|         this.createUniqTaskTimer(3600, SendOnAdventureTask.name); | ||||
|         this.createUniqTaskTimer(1200, BalanceHeroResourcesTask.name); | ||||
|         this.createUniqTaskTimer(180, GrabVillageState.name); | ||||
|         this.createUniqTaskTimer(300, UpdateResourceContracts.name); | ||||
|     } | ||||
|  | ||||
|     private scheduleUniqTask(seconds: number, name: string, args: Args = {}) { | ||||
|     public createUniqTaskTimer(seconds: number, name: string, args: Args = {}) { | ||||
|         const taskScheduler = () => { | ||||
|             if (!this.taskQueue.has(t => t.name === name)) { | ||||
|                 this.scheduleTask(name, args, timestamp() + Math.min(seconds, 5 * 60)); | ||||
|             } | ||||
|             this.scheduleUniqTask(name, args, timestamp() + Math.min(seconds, 5 * 60)); | ||||
|         }; | ||||
|         taskScheduler(); | ||||
|         setInterval(taskScheduler, seconds * 1000); | ||||
| @@ -63,6 +66,13 @@ export class Scheduler { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     scheduleUniqTask(name: string, args: Args, ts?: number | undefined): void { | ||||
|         let alreadyHasTask = this.taskQueue.has(t => t.name === name); | ||||
|         if (!alreadyHasTask) { | ||||
|             this.scheduleTask(name, args, ts); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     completeTask(id: TaskId) { | ||||
|         this.taskQueue.remove(id); | ||||
|         this.actionQueue.clear(); | ||||
| @@ -87,6 +97,13 @@ export class Scheduler { | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     updateResources(taskId: TaskId, resources: Resources): void { | ||||
|         this.taskQueue.modify( | ||||
|             t => t.id === taskId, | ||||
|             t => withResources(t, resources) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     scheduleActions(actions: Array<Command>): void { | ||||
|         this.actionQueue.assign(actions); | ||||
|     } | ||||
| @@ -94,6 +111,15 @@ export class Scheduler { | ||||
|     clearActions() { | ||||
|         this.actionQueue.clear(); | ||||
|     } | ||||
|  | ||||
|     getVillageRequiredResources(villageId): ResourcesInterface | undefined { | ||||
|         const tasks = this.taskQueue.seeItems().filter(t => isBuildingTask(t.name) && sameVillage(villageId, t.args)); | ||||
|         const first = tasks.shift(); | ||||
|         if (first && first.args.resources) { | ||||
|             return first.args.resources; | ||||
|         } | ||||
|         return undefined; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function isBuildingTask(taskName: string) { | ||||
| @@ -104,10 +130,14 @@ function sameVillage(villageId: number | undefined, args: Args) { | ||||
|     return villageId !== undefined && args.villageId === villageId; | ||||
| } | ||||
|  | ||||
| export function withTime(task: Task, ts: number): Task { | ||||
| function withTime(task: Task, ts: number): Task { | ||||
|     return new Task(task.id, ts, task.name, task.args); | ||||
| } | ||||
|  | ||||
| function withResources(task: Task, resources: ResourcesInterface): Task { | ||||
|     return new Task(task.id, task.ts, task.name, { ...task.args, resources }); | ||||
| } | ||||
|  | ||||
| function calculateTimeToPushAfter(tasks: TaskList, predicate: (t: Task) => boolean, ts: number | undefined): number { | ||||
|     const normalizedTs = ts || timestamp(); | ||||
|     const queuedTaskIndex = findLastIndex(tasks, predicate); | ||||
|   | ||||
| @@ -107,7 +107,7 @@ export class TaskQueue { | ||||
|     } | ||||
|  | ||||
|     private flushItems(items: TaskList): void { | ||||
|         const normalized = items.sort((x, y) => x.ts - y.ts); | ||||
|         const normalized = items.sort((x, y) => x.ts - y.ts || x.id.localeCompare(y.id)); | ||||
|         this.storage.set(QUEUE_NAME, normalized); | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										35
									
								
								src/Task/UpdateResourceContracts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/Task/UpdateResourceContracts.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| import { Args, Command } from '../Common'; | ||||
| import { Task } from '../Storage/TaskQueue'; | ||||
| import { TaskController, registerTask } from './TaskController'; | ||||
| import { GoToPageAction } from '../Action/GoToPageAction'; | ||||
| import { path } from '../utils'; | ||||
| import { UpgradeBuildingTask } from './UpgradeBuildingTask'; | ||||
| import { UpdateBuildingTaskResourcesAction } from '../Action/UpdateBuildingTaskResourcesAction'; | ||||
| import { CompleteTaskAction } from '../Action/CompleteTaskAction'; | ||||
|  | ||||
| @registerTask | ||||
| export class UpdateResourceContracts extends TaskController { | ||||
|     async run(task: Task) { | ||||
|         const args: Args = { ...task.args, taskId: task.id }; | ||||
|  | ||||
|         const actions: Array<Command> = []; | ||||
|  | ||||
|         const tasks = this.scheduler.getTaskItems(); | ||||
|         for (let task of tasks) { | ||||
|             const { villageId, buildId } = task.args; | ||||
|             if (task.name === UpgradeBuildingTask.name && villageId && buildId) { | ||||
|                 actions.push( | ||||
|                     new Command(GoToPageAction.name, { | ||||
|                         ...args, | ||||
|                         path: path('/build.php', { newdid: villageId, id: buildId }), | ||||
|                     }) | ||||
|                 ); | ||||
|                 actions.push(new Command(UpdateBuildingTaskResourcesAction.name, { ...args, taskId: task.id })); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         actions.push(new Command(CompleteTaskAction.name, args)); | ||||
|  | ||||
|         this.scheduler.scheduleActions(actions); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user