Advertisement
Guest User

Untitled

a guest
Sep 12th, 2016
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function solve() {
  2.     'use strict';
  3.  
  4.     const ERROR_MESSAGES = {
  5.         INVALID_NAME_TYPE: 'Name must be string!',
  6.         INVALID_NAME_LENGTH: 'Name must be between between 2 and 20 symbols long!',
  7.         INVALID_NAME_SYMBOLS: 'Name can contain only latin symbols and whitespaces!',
  8.         INVALID_MANA: 'Mana must be a positive integer number!',
  9.         INVALID_EFFECT: 'Effect must be a function with 1 parameter!',
  10.         INVALID_DAMAGE: 'Damage must be a positive number that is at most 100!',
  11.         INVALID_HEALTH: 'Health must be a positive number that is at most 200!',
  12.         INVALID_SPEED: 'Speed must be a positive number that is at most 100!',
  13.         INVALID_COUNT: 'Count must be a positive integer number!',
  14.         INVALID_SPELL_OBJECT: 'Passed objects must be Spell-like objects!',
  15.         NOT_ENOUGH_MANA: 'Not enough mana!',
  16.         TARGET_NOT_FOUND: 'Target not found!',
  17.         INVALID_BATTLE_PARTICIPANT: 'Battle participants must be ArmyUnit-like!'
  18.     };
  19.  
  20.  
  21.     class Spell {
  22.         constructor(name, manaCost, effect) {
  23.             this.name = name;
  24.             this.manaCost = manaCost;
  25.             this.effect = effect;
  26.         }
  27.  
  28.         get name() {
  29.             return this._name;
  30.         }
  31.  
  32.         set name(value) {
  33.             if (typeof(value) !== 'string') {
  34.                 throw  new Error(ERROR_MESSAGES.INVALID_NAME_TYPE);
  35.             }
  36.             if (value.length < 2 || value.length > 20) {
  37.                 throw new Error(ERROR_MESSAGES.INVALID_NAME_LENGTH);
  38.             }
  39.             if (!/^[a-zA-Z\s]+$/g.test(value)) {
  40.                 throw new Error(ERROR_MESSAGES.INVALID_NAME_SYMBOLS);
  41.             }
  42.             this._name = value;
  43.         }
  44.  
  45.         get effect() {
  46.             return this._effect;
  47.         }
  48.  
  49.         set effect(value) {
  50.             if (typeof (value) !== 'function') {
  51.                 throw new Error('Effect must be a function with 1 parameter!');
  52.             } else if (value.length !== 1) {
  53.                 throw new Error('Effect must be a function with 1 parameter!');
  54.             }
  55.  
  56.             this._effect = value;
  57.         }
  58.  
  59.         get manaCost() {
  60.             return this._manaCost;
  61.         }
  62.  
  63.         set manaCost(value) {
  64.             if (value < 0) {
  65.                 throw new Error(ERROR_MESSAGES.INVALID_MANA);
  66.             }
  67.             this._manaCost = value;
  68.         }
  69.     }
  70.  
  71.     class Unit {
  72.         constructor(name, alignment) {
  73.             this.name = name;
  74.             this.alignment = alignment;
  75.         }
  76.  
  77.         get name() {
  78.             return this._name;
  79.         }
  80.  
  81.         set name(value) {
  82.             if (typeof(value) !== 'string') {
  83.                 throw  new Error(ERROR_MESSAGES.INVALID_NAME_TYPE);
  84.             }
  85.             if (value.length < 2 || value.length > 20) {
  86.                 throw new Error(ERROR_MESSAGES.INVALID_NAME_LENGTH);
  87.             }
  88.             if (!/^[a-zA-Z\s]+$/g.test(value)) {
  89.                 throw new Error(ERROR_MESSAGES.INVALID_NAME_SYMBOLS);
  90.             }
  91.             this._name = value;
  92.         }
  93.  
  94.         get alignment() {
  95.             return this._alignment;
  96.         }
  97.  
  98.         set alignment(value) {
  99.             if (value.toLowerCase() !== 'good' && value.toLowerCase() !== 'neutral' && value.toLowerCase() !== 'evil') {
  100.                 throw new Error('Alignment must be good, neutral or evil!');
  101.             }
  102.             this._alignment = value;
  103.         }
  104.     }
  105.  
  106.     let armyUnitId = 1;
  107.  
  108.     class ArmyUnit extends Unit {
  109.         constructor(name, alignment, damage, health, count, speed) {
  110.             super(name, alignment);
  111.             this.id = armyUnitId;
  112.             this.damage = damage;
  113.             this.health = health;
  114.             this.count = count;
  115.             this.speed = speed;
  116.             armyUnitId += 1;
  117.         }
  118.  
  119.         get damage() {
  120.             return this._damage;
  121.         }
  122.  
  123.         set damage(value) {
  124.             if (value < 0 || value > 100) {
  125.                 throw new Error('Damage must be a positive number that is at most 100!');
  126.             }
  127.             this._damage = value;
  128.         }
  129.  
  130.         get health() {
  131.             return this._health;
  132.         }
  133.  
  134.         set health(value) {
  135.             if (value < 0 || value >= 200) {
  136.                 throw new Error('Health must be a positive number that is at most 200!');
  137.             }
  138.             this._health = value;
  139.         }
  140.  
  141.         get count() {
  142.             return this._count;
  143.         }
  144.  
  145.         set count(value) {
  146.             if (typeof (value) !== 'number') {
  147.                 throw Error('Count must be a positive integer number!');
  148.             } else if (value < 0) {
  149.                 throw Error('Count must be a positive integer number!');
  150.             }
  151.             this._count = value;
  152.         }
  153.  
  154.         get speed() {
  155.             return this._speed;
  156.         }
  157.  
  158.         set speed(value) {
  159.             if (value <= 0 || value >= 100) {
  160.                 throw new Error('Speed must be a positive number that is at most 100!');
  161.             }
  162.             this._speed = value;
  163.         }
  164.     }
  165.  
  166.     class Commander extends Unit {
  167.         constructor(name, alignment, damage, health, count, speed, mana) {
  168.             super(name, alignment, damage, health, count, speed);
  169.             this.mana = mana;
  170.             this.spellbook = [];
  171.             this.army = [];
  172.         }
  173.  
  174.         get mana() {
  175.             return this._mana;
  176.         }
  177.  
  178.         set mana(value) {
  179.             if (isNaN(value) || Number(value) < 0) {
  180.                 throw new Error(ERROR_MESSAGES.INVALID_MANA);
  181.             }
  182.             this._mana = value;
  183.         }
  184.     }
  185.  
  186.     const battlemanager = {
  187.         commanders: [],
  188.         getCommander(name, alignment, mana) {
  189.             return new Commander(name, alignment, 0, 0, 0, 0, mana);
  190.         },
  191.         getArmyUnit(options) {
  192.             return new ArmyUnit(options.name, options.alignment, options.damage, options.health, options.count, options.speed);
  193.         },
  194.         getSpell(name, manaCost, effect) {
  195.             return new Spell(name, manaCost, effect);
  196.         },
  197.         addCommanders(params) {
  198.             for (let i = 0; i < arguments.length; i += 1) {
  199.                 this.commanders.push(arguments[i]);
  200.             }
  201.             return this;
  202.         },
  203.         addArmyUnitTo(commanderName, armyUnit) {
  204.             let commander = this.commanders.find(c => c.name === commanderName);
  205.             if (commander !== undefined) {
  206.                 commander.army.push(armyUnit);
  207.             }
  208.             return this;
  209.         },
  210.         addSpellsTo(commanderName, spell1, spell2, spell3) {
  211.             let commander = this.commanders.find(c => c.name === commanderName),
  212.                 spellsToAdd = Array.from(arguments).splice(1, arguments.length - 1);
  213.  
  214.             if (commander !== undefined) {
  215.                 spellsToAdd.forEach(sp => {
  216.                     if (!sp.name || !sp.manaCost || !sp.effect) {
  217.                         throw new Error('Passed objects must be Spell-like objects!')
  218.                     }
  219.                 });
  220.                 spellsToAdd.forEach(sp => {
  221.                     let value = sp.name;
  222.                     if (typeof(value) !== 'string') {
  223.                         throw  new Error(ERROR_MESSAGES.INVALID_SPELL_OBJECT);
  224.                     }
  225.                     if (value.length < 2 || value.length > 20) {
  226.                         throw new Error(ERROR_MESSAGES.INVALID_SPELL_OBJECT);
  227.                     }
  228.                     if (!/^[a-zA-Z\s]+$/g.test(value)) {
  229.                         throw new Error(ERROR_MESSAGES.INVALID_SPELL_OBJECT);
  230.                     }
  231.                     if (sp.manaCost < 0) {
  232.                         throw new Error(ERROR_MESSAGES.INVALID_SPELL_OBJECT);
  233.                     }
  234.                     /* if (typeof(sp.effect) !== 'function') {
  235.                         throw new Error(ERROR_MESSAGES.INVALID_SPELL_OBJECT);
  236.                     } else if (typeof(sp.effect)) {
  237.                         throw new Error(ERROR_MESSAGES.INVALID_SPELL_OBJECT);
  238.                     } */
  239.                 });
  240.                 spellsToAdd.forEach(sp => commander.spellbook.push(sp));
  241.                 return this;
  242.             } else {
  243.                 throw new Error(ERROR_MESSAGES.INVALID_SPELL_OBJECT);
  244.             }
  245.         },
  246.         findCommanders(query) {
  247.             let keys = Object.keys(query),
  248.                 result = [];
  249.  
  250.             this.commanders.forEach(c => {
  251.                 let isValid = true;
  252.                 for (let i = 0; i < keys.length; i += 1) {
  253.                     let key = keys[i];
  254.                     if (c[key] !== query[key]) {
  255.                         isValid = false;
  256.                         break;
  257.                     }
  258.                 }
  259.                 if (isValid) {
  260.                     result.push(c);
  261.                 }
  262.             });
  263.             return result.sort((a, b) => {
  264.                 if (a.name > b.name) {
  265.                     return 1;
  266.                 } else if (a.name < b.name) {
  267.                     return -1;
  268.                 } else {
  269.                     return 0;
  270.                 }
  271.             });
  272.         },
  273.         findArmyUnitById(id) {
  274.             for (let i = 0; i < this.commanders.length; i += 1) {
  275.                 let currentCommander = this.commanders[i];
  276.  
  277.                 for (let j = 0; j < currentCommander.army.length; j += 1) {
  278.                     let unit = currentCommander.army[j];
  279.                     if (unit.id === id) {
  280.                         return unit;
  281.                     }
  282.                 }
  283.             }
  284.             return undefined;
  285.         },
  286.         findArmyUnits(query) {
  287.             let keys = Object.keys(query),
  288.                 found = [];
  289.  
  290.             for (let i = 0; i < this.commanders.length; i += 1) {
  291.                 let currentCommander = this.commanders[i];
  292.                 for (let unit of currentCommander.army) {
  293.                     let isValid = true;
  294.                     for (let j = 0; j < keys.length; j += 1) {
  295.                         let key = keys[j];
  296.                         let unitValue = unit[key];
  297.                         let queryValue = query[key];
  298.                         if (unit[key] !== query[key]) {
  299.                             isValid = false;
  300.                             break;
  301.                         }
  302.                     }
  303.  
  304.                     if (isValid) {
  305.                         found.push(unit);
  306.                     }
  307.                 }
  308.             }
  309.  
  310.             let result = found.sort((a, b) => {
  311.                 if (a.speed === b.speed) {
  312.                     if (a.name > b.name) {
  313.                         return 1;
  314.                     } else if (a.name < b.name) {
  315.                         return -1;
  316.                     }
  317.                     return 0;
  318.                 }
  319.                 return b.speed - a.speed;
  320.             });
  321.             return result;
  322.         },
  323.         spellcast(casterName, spellName, targetUnitId) {
  324.             let commander = this.commanders.find(c => c.name === casterName);
  325.             if (commander === undefined) {
  326.                 throw new Error("Cannot cast with non-existant commander " + casterName);
  327.             }
  328.  
  329.             let effect,
  330.                 cost;
  331.             for (let i = 0; i < commander.spellbook.length; i += 1) {
  332.                 let currentSpell = commander.spellbook[i];
  333.                 if (currentSpell.name === spellName) {
  334.                     effect = currentSpell.effect;
  335.                     cost = currentSpell.manaCost;
  336.                     break;
  337.                 }
  338.             }
  339.  
  340.             if (effect == undefined) {
  341.                 throw new Error(casterName + " does not know " + spellName);
  342.             }
  343.  
  344.             if (cost > commander.mana) {
  345.                 throw new Error(ERROR_MESSAGES.NOT_ENOUGH_MANA);
  346.             }
  347.  
  348.             commander.mana -= cost;
  349.             let armyUnit;
  350.             this.commanders.forEach(c => {
  351.                 for (let i = 0; i < c.army.length; i += 1) {
  352.                     let unit = c.army[i];
  353.                     if (unit.id === targetUnitId) {
  354.                         armyUnit = unit;
  355.                         break;
  356.                     }
  357.                 }
  358.             });
  359.  
  360.             if (armyUnit === undefined) {
  361.                 throw new Error('Target not found!');
  362.             }
  363.  
  364.             effect(armyUnit);
  365.             return this;
  366.         },
  367.         battle(attacker, defender) {
  368.             if (!attacker.damage || !attacker.health || !attacker.count) {
  369.                 throw new Error('Battle participants must be ArmyUnit-like!');
  370.             }
  371.  
  372.             if (!defender.damage || !defender.health || !defender.count) {
  373.                 throw new Error('Battle participants must be ArmyUnit-like!');
  374.             }
  375.  
  376.             attacker.totalDamage = attacker.count * attacker.damage;
  377.             defender.totalHealth = defender.health * defender.count;
  378.             defender.totalHealth -= attacker.totalDamage;
  379.             let newCount = Math.ceil(defender.totalHealth / defender.health);
  380.             if (newCount < 0) {
  381.                 defender.count = 0;
  382.             } else {
  383.                 defender.count = newCount;
  384.             }
  385.             return this;
  386.         }
  387.     };
  388.  
  389.     return battlemanager;
  390. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement