Skip to content

Commit

Permalink
refactoring: Modified into Model-View-Controller architecture. (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
MinoruSekine committed Jun 9, 2024
1 parent ae482e9 commit 5047db0
Show file tree
Hide file tree
Showing 3 changed files with 351 additions and 30 deletions.
339 changes: 319 additions & 20 deletions nol_tsukumo.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
/**
* Tsukumo status of a weapon.
*/
class TsukumoStatus {
class NolTsukumoStatus {
level;
exp;
numOfActivatedTsukumo;
Expand Down Expand Up @@ -91,7 +91,7 @@ function getExpToNextLevel(level) {
/**
* Calculate exp to specified level.
*
* @param {TsukumoStatus} currentStatus - Current Tsukumo status
* @param {NolTsukumoStatus} currentStatus - Current Tsukumo status
* @param {number} toLevel - Level to raise
* @return {number} Necessary exp to toLevel
*/
Expand All @@ -118,7 +118,7 @@ function getExpPerATsukumoSource(gain, activeTsukumoNum) {
/**
* Calculate number of tsukumo source to specified level.
*
* @param {TsukumoStatus} currentStatus - Current Tsukumo status
* @param {NolTsukumoStatus} currentStatus - Current Tsukumo status
* @param {number} toLevel - Level to raise
* @param {number} gain - Multiplier for exp, usually x1.0, and x1.5 in campaign
* @return {number} Number of necessary tsukumo source to toLevel
Expand All @@ -133,7 +133,7 @@ function calcTsukumoSourceToSpecifiedLevel(currentStatus, toLevel, gain) {
/**
* Validate current inputs to calculate.
*
* @param {TsukumoStatus} currentStatus - Current Tsukumo status
* @param {NolTsukumoStatus} currentStatus - Current Tsukumo status
* @param {number} toLevel - Level to raise
* @return {boolean} Enabled to calculate or not
*/
Expand All @@ -142,6 +142,312 @@ function isEnabledToCalculate(currentStatus, toLevel) {
(currentStatus.exp < getExpToNextLevel(currentStatus.level)));
}

/**
* Interface to observe NolTsukumoModel.
*/
class NolTsukumoModelObserverInterface {
/**
* Call when current exp has been updated.
* @param {number} exp - Updated current exp
*/
onUpdateCurrentExp(exp) {
}
/**
* Call when current level has been updated.
* @param {number} level - Updated current level
*/
onUpdateCurrentLevel(level) {
}
/**
* Call when max exp of current level has been updated.
* @param {number} maxExp - Updated max exp of current level
*/
onUpdateMaxExpOfCurrentLevel(maxExp) {
}
/**
* Call when to level has been updated.
* @param {number} toLevel - Updated "to level"
*/
onUpdateToLevel(toLevel) {
}
/**
* Call when min of to level has been updated.
* @param {number} toLevelMin - Updated min of "to level"
*/
onUpdateToLevelMin(toLevelMin) {
}
/**
* Call when necessary tsukumo exp and number of source have been updated.
* @param {number} exp - Updated exp to specified level.
* @param {number} source - Updated number of source to specified level.
*/
onUpdateNecessaryTsukumo(exp, source) {
}
}

/**
* Model of Nol Tsukumo calculator.
*/
class NolTsukumoModel {
#currentStatus = new NolTsukumoStatus(0, 0, 0);
#toLevel = 1;
#toLevelMin = 1;
#gain = 1.0;
#observers = [];
/**
* Notify necessary Tsukumo exp and sources to observers.
*/
#notifyNecessaryTsukumo() {
const necessaryExp =
calcExpToSpecifiedLevel(this.#currentStatus, this.#toLevel);
const necessarySource = necessaryExp / (10 * this.#gain);
this.#observers.forEach((observer) => {
observer.onUpdateNecessaryTsukumo(necessaryExp, necessarySource);
});
}
/**
* Initialize model instance.
*/
initialize() {
this.setCurrentLevel(0);
this.setCurrentExp(0);
this.setCurrentNumOfActuvatedTsukumo(0);
this.setToLevel(1);
this.setGain(1.0);
}
/**
* Set current Tsukmo level.
* @param {number} level - Current Tsukumo level
*/
setCurrentLevel(level) {
this.#currentStatus.level = level;
this.#currentStatus.maxExpOfCurrentLevel = getExpToNextLevel(level);
if (false) {
for (const observer in this.#observers) {
observer.onUpdateCurrentLevel(level);

const max = getExpToNextLevel(level) - 1;
observer.onUpdateMaxExpToNextLevel(max);

if (this.#currentStatus.level >= this.#toLevelMin) {
this.#toLevelMin = this.#currentStatus.level + 1;
observer.onUpdateToLevelMin(this.#toLevelMin);
if (this.#toLevel < this.#toLevelMin) {
this.#toLevel = this.#toLevelMin;
observer.onUpdateToLevel(this.#toLevel);
}
}
}
} else {
this.#observers.forEach((observer) => {
observer.onUpdateCurrentLevel(level);

const max = getExpToNextLevel(level) - 1;
observer.onUpdateMaxExpOfCurrentLevel(max);

if (this.#currentStatus.level >= this.#toLevelMin) {
this.#toLevelMin = this.#currentStatus.level + 1;
observer.onUpdateToLevelMin(this.#toLevelMin);
if (this.#toLevel < this.#toLevelMin) {
this.#toLevel = this.#toLevelMin;
observer.onUpdateToLevel(this.#toLevel);
}
}
});
}
this.#notifyNecessaryTsukumo();
}
/**
* Set current Tsukmo exp.
* @param {number} exp - Current Tsukumo exp
*/
setCurrentExp(exp) {
this.#currentStatus.exp = exp;
this.#notifyNecessaryTsukumo();
}
/**
* Set current Tsukmo exp.
* @param {number} numOfActivatedTsukumo - Current number of activated tsukmo
*/
setCurrentNumOfActuvatedTsukumo(numOfActivatedTsukumo) {
this.#currentStatus.numOfActivatedTsukumo = numOfActivatedTsukumo;
this.#notifyNecessaryTsukumo();
}
/**
* Set "to level".
* @param {number} level - Expected "to level".
*/
setToLevel(level) {
this.#toLevel = level;
this.#notifyNecessaryTsukumo();
}
/**
* Set gain of tsukumo source into tsukumo exp.
* @param {number} gain - Gain of tsukumo source into tsukumo exp
*/
setGain(gain) {
this.#gain = gain;
this.#notifyNecessaryTsukumo();
}
/**
* Register observer of model.
* @param {NolTsukumoModelObserverInterface} observer - Observer to Register.
*/
registerObserver(observer) {
this.#observers.push(observer);
}
}

/**
* View of Nol Tsukumo calculator.
*/
class NolTsukumoView extends NolTsukumoModelObserverInterface {
#currentExpInput = document.getElementById('exp-input');
#toLevelInput = document.getElementById('to-level-input');
#necessaryExpInput = document.getElementById('tsukumo-exp-input');
#necessarySourceInput = document.getElementById('tsukumo-source-input');

#model = null;
/**
* Constructor of view.
* @param {NolTsukumoModel} model - Instance of model.
*/
constructor(model) {
super();

this.#model = model;
this.#model.registerObserver(this);
}
/**
* Call when current exp has been updated.
* @param {number} exp - Updated max exp of current level
*/
onUpdateCurrentExp(exp) {
this.#currentExpInput.value = exp;
}
/**
* Call when current level has been updated.
* @param {number} level - Updated current level
*/
onUpdateCurrentLevel(level) {
}
/**
* Call when max exp of current level has been updated.
* @param {number} maxExp - Updated max exp of current level
*/
onUpdateMaxExpOfCurrentLevel(maxExp) {
}
/**
* Call when to level has been updated.
* @param {number} toLevel - Updated "to level"
*/
onUpdateToLevel(toLevel) {
this.#toLevelInput.value = toLevel;
}
/**
* Call when min of to level has been updated.
* @param {number} toLevelMin - Updated min of "to level"
*/
onUpdateToLevelMin(toLevelMin) {
}
/**
* Call when necessary tsukumo exp and number of source have been updated.
* @param {number} exp - Updated exp to specified level.
* @param {number} source - Updated number of source to specified level.
*/
onUpdateNecessaryTsukumo(exp, source) {
this.#necessaryExpInput.value = exp;
this.#necessarySourceInput.value = source;
}
}

/**
* Controller of Nol Tsukumo calculator.
*/
class NolTsukumoController extends NolTsukumoModelObserverInterface {
#toLevelInput = document.getElementById('to-level-input');
#currentLevelInput = document.getElementById('current-level-input');
#currentExpInput = document.getElementById('exp-input');
#currentNumOfActivatedTsukumo =
document.getElementById('active-tsukumo-num-input');
#gainInput = document.getElementById('tsukumo-gain-input');

#model = null;

/**
* Constructor of NolTsukumoController.
* @param {NolTsukumoModel} model - Instance of model.
*/
constructor(model) {
super();

this.#model = model;
this.#model.registerObserver(this);

this.#currentLevelInput.addEventListener('input', () => {
this.#model.setCurrentLevel(parseInt(this.#currentLevelInput.value, 10));
});

this.#currentExpInput.addEventListener('input', () => {
this.#model.setCurrentExp(parseInt(this.#currentExpInput.value, 10));
});

this.#currentNumOfActivatedTsukumo.addEventListener('input', () => {
const numActivated =
parseInt(this.#currentNumOfActivatedTsukumo.value, 10);
this.#model.setCurrentNumOfActuvatedTsukumo(numActivated);
});

this.#toLevelInput.addEventListener('input', () => {
this.#model.setToLevel(parseInt(this.#toLevelInput.value, 10));
});

this.#gainInput.addEventListener('input', () => {
this.#model.setGain(parseInt(this.#gainInput.value, 10));
});
}
/**
* Call when current exp has been updated.
* @param {number} exp - Updated max exp of current level
*/
onUpdateCurrentExp(exp) {
}
/**
* Call when current level has been updated.
* @param {number} level - Updated current level
*/
onUpdateCurrentLevel(level) {
this.#toLevelInput.min = level + 1;
}
/**
* Call when max exp of current level has been updated.
* @param {number} maxExp - Updated max exp of current level
*/
onUpdateMaxExpOfCurrentLevel(maxExp) {
this.#currentExpInput.max = maxExp;
}
/**
* Call when to level has been updated.
* @param {number} toLevel - Updated "to level"
*/
onUpdateToLevel(toLevel) {
}
/**
* Call when min of to level has been updated.
* @param {number} toLevelMin - Updated min of "to level"
*/
onUpdateToLevelMin(toLevelMin) {
this.#toLevelInput.min = toLevelMin;
}
/**
* Call when necessary tsukumo exp and number of source have been updated.
* @param {number} exp - Updated exp to specified level.
* @param {number} source - Updated number of source to specified level.
*/
onUpdateNecessaryTsukumo(exp, source) {
}
}

/**
* Update all elements on HTML by current inputs.
*/
Expand All @@ -161,7 +467,7 @@ function update() {
parseInt(document.getElementById('active-tsukumo-num-input').value, 10);

const currentStatus =
new TsukumoStatus(currentLevel, currentExp, activeTsukumoNum);
new NolTsukumoStatus(currentLevel, currentExp, activeTsukumoNum);

const toLevelInput = document.getElementById('to-level-input');
const minToLevel = currentLevel + 1;
Expand All @@ -181,20 +487,13 @@ function update() {
}
}

window.onload = () => {
const idToUpdateByChange = [
'current-level-input',
'exp-input',
'active-tsukumo-num-input',
'to-level-input',
'tsukumo-gain-input',
];
idToUpdateByChange.forEach((id) => {
const input = document.getElementById(id);
input.addEventListener('input', () => {
update();
});
});
let gModel = null;
let gView = null;
let gController = null;

update();
window.onload = () => {
gModel = new NolTsukumoModel();
gView = new NolTsukumoView(gModel);
gController = new NolTsukumoController(gModel);
gModel.initialize();
};
Loading

0 comments on commit 5047db0

Please sign in to comment.