오윤석

스펙 계산 기능 추가

1 +module.exports = {
2 + '한손검': 1.2,
3 + '한손도끼': 1.2,
4 + '한손둔기': 1.2,
5 + '스태프': 1,
6 + '완드': 1,
7 + '샤이닝 로드': 1.2,
8 + '단검': 1.3,
9 + '케인': 1.3,
10 + '데스페라도': 1.3,
11 + '에너지소드': 1.5,
12 + '소울 슈터': 1.7,
13 + 'ESP 리미터': 1.2,
14 + '체인': 1.3,
15 + '매직 건틀렛': 1.2,
16 + '부채': 1.3,
17 + '튜너': 1.3,
18 + '두손검': 1.34,
19 + '두손도끼': 1.34,
20 + '두손둔기': 1.34,
21 + '창': 1.34,
22 + '폴암': 1.49,
23 + '태도': 1.34,
24 + '건틀렛 리볼버': 1.7,
25 + '활': 1.3,
26 + '석궁': 1.35,
27 + '듀얼 보우건': 1.3,
28 + '에인션트 보우': 1.3,
29 + '아대': 1.75,
30 + '건': 1.5,
31 + '너클': 1.7,
32 + '핸드캐논': 1.5
33 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -144,6 +144,7 @@ const analyzeEquipment = async function(nickname, characterCode, job) { ...@@ -144,6 +144,7 @@ const analyzeEquipment = async function(nickname, characterCode, job) {
144 let damagePercent = 0; 144 let damagePercent = 0;
145 let majorPercent = 0; 145 let majorPercent = 0;
146 let attackPowerPercent = 0; 146 let attackPowerPercent = 0;
147 + let weapon = undefined;
147 const equipmentURLs = []; 148 const equipmentURLs = [];
148 $(".tab01_con_wrap .weapon_wrap .item_pot li span a").each(async function() { 149 $(".tab01_con_wrap .weapon_wrap .item_pot li span a").each(async function() {
149 equipmentURLs.push("https://maplestory.nexon.com" + $(this).attr("href")); 150 equipmentURLs.push("https://maplestory.nexon.com" + $(this).attr("href"));
...@@ -159,13 +160,18 @@ const analyzeEquipment = async function(nickname, characterCode, job) { ...@@ -159,13 +160,18 @@ const analyzeEquipment = async function(nickname, characterCode, job) {
159 const equipmentDom = new JSDOM(equipmentResp.data.view); 160 const equipmentDom = new JSDOM(equipmentResp.data.view);
160 const $equipment = (require('jquery'))(equipmentDom.window); 161 const $equipment = (require('jquery'))(equipmentDom.window);
161 162
163 + const equipmentType = $equipment(".item_ability .ablilty02:eq(1) .job_name em").text();
164 + if (equipmentType.indexOf("손무기") >= 0 && equipmentType.indexOf("블레이드") < 0 && equipmentType.indexOf("대검") < 0) {
165 + weapon = equipmentType.split(" (")[0];
166 + }
167 +
162 $equipment(".stet_info ul li").each(function() { 168 $equipment(".stet_info ul li").each(function() {
163 - const regexMajor1 = new RegExp(`${jobModel[job].major} : \\+(\\d)%`); 169 + const regexMajor1 = new RegExp(`${jobModel[job].major} : \\+(\\d+)%`);
164 - const regexMajor2 = new RegExp(`올스탯 : \\+(\\d)%`); 170 + const regexMajor2 = new RegExp(`올스탯 : \\+(\\d+)%`);
165 const regexAttackPower = (jobModel[job].major == "INT") ? 171 const regexAttackPower = (jobModel[job].major == "INT") ?
166 - new RegExp(`마력 : \\+(\\d)%`) : 172 + new RegExp(`마력 : \\+(\\d+)%`) :
167 - new RegExp(`공격력 : \\+(\\d)%`); 173 + new RegExp(`공격력 : \\+(\\d+)%`);
168 - const regexDamage = new RegExp(`데미지 : \\+(\\d)%`); 174 + const regexDamage = new RegExp(`^데미지 : \\+(\\d+)%`);
169 175
170 if ($(this).find(".stet_th span").text() == "올스탯") { 176 if ($(this).find(".stet_th span").text() == "올스탯") {
171 majorPercent += parseInt($(this).find(".point_td font:eq(0)").text().substring(1)); 177 majorPercent += parseInt($(this).find(".point_td font:eq(0)").text().substring(1));
...@@ -191,7 +197,8 @@ const analyzeEquipment = async function(nickname, characterCode, job) { ...@@ -191,7 +197,8 @@ const analyzeEquipment = async function(nickname, characterCode, job) {
191 majorArcane: majorArcane, 197 majorArcane: majorArcane,
192 majorPercent: majorPercent, 198 majorPercent: majorPercent,
193 attackPowerPercent: attackPowerPercent, 199 attackPowerPercent: attackPowerPercent,
194 - damagePercent: damagePercent 200 + damagePercent: damagePercent,
201 + weapon: weapon
195 }; 202 };
196 } catch (error) { 203 } catch (error) {
197 console.log(error); 204 console.log(error);
...@@ -199,6 +206,146 @@ const analyzeEquipment = async function(nickname, characterCode, job) { ...@@ -199,6 +206,146 @@ const analyzeEquipment = async function(nickname, characterCode, job) {
199 } 206 }
200 } 207 }
201 208
209 +const analyzeStats = function(characterInfo, analysisEquipment) {
210 + const jobModel = require('../model/job');
211 + const job = jobModel[characterInfo.character.job];
212 + const jobDefault = jobModel.default;
213 + const weaponConst = require('../model/weapon')[analysisEquipment.weapon] || 1;
214 + const stats = {
215 + major: {
216 + pure: 0,
217 + percent: analysisEquipment.majorPercent +
218 + job.stats.passive.major.percent +
219 + jobDefault.stats.passive.major.percent,
220 + added: 0
221 + },
222 + minor: characterInfo.stats.minor,
223 + damage: {
224 + all: characterInfo.stats.damageHyper +
225 + analysisEquipment.damagePercent +
226 + job.stats.passive.damage.all +
227 + jobDefault.stats.passive.damage.all,
228 + boss: characterInfo.stats.bossAttackDamage
229 + },
230 + finalDamage: job.stats.passive.finalDamage,
231 + criticalDamage: characterInfo.stats.criticalDamage,
232 + attackPower: {
233 + pure: 0,
234 + percent: analysisEquipment.attackPowerPercent +
235 + job.stats.passive.attackPower.percent
236 + },
237 + ignoreGuard: characterInfo.stats.ignoreGuard
238 + };
239 +
240 + stats.major.added = characterInfo.stats.majorHyper +
241 + analysisEquipment.majorArcane;
242 + stats.major.pure = (characterInfo.stats.major - stats.major.added) / (1 + stats.major.percent / 100);
243 +
244 + stats.attackPower.pure = characterInfo.stats.statAttackPower * 100 / (characterInfo.stats.major * 4 + stats.minor) / job.jobConst / weaponConst / (1 + stats.attackPower.percent / 100) / (1 + stats.damage.all / 100) / (1 + stats.finalDamage / 100);
245 +
246 + return stats;
247 +}
248 +
249 +const calculateEfficiency = function(stats, job, weapon) {
250 + const efficiency = {
251 + major: {
252 + pure: 1,
253 + percent: 0
254 + },
255 + attackPower: {
256 + pure: 0,
257 + percent: 0,
258 + },
259 + damage: 0,
260 + criticalDamage: 0,
261 + ignoreGuard: 0
262 + };
263 +
264 + const defaultPower = calculatePower(stats, job, weapon);
265 +
266 + stats.major.pure += 1;
267 + const majorPure = calculatePower(stats, job, weapon) - defaultPower;
268 + stats.major.pure -= 1;
269 +
270 + if (majorPure == 0)
271 + return efficiency;
272 +
273 + stats.major.percent += 1;
274 + efficiency.major.percent = (calculatePower(stats, job, weapon) - defaultPower) / majorPure;
275 + stats.major.percent -= 1;
276 +
277 + stats.attackPower.pure += 1;
278 + efficiency.attackPower.pure = (calculatePower(stats, job, weapon) - defaultPower) / majorPure;
279 + stats.attackPower.pure -= 1;
280 +
281 + stats.attackPower.percent += 1;
282 + efficiency.attackPower.percent = (calculatePower(stats, job, weapon) - defaultPower) / majorPure;
283 + stats.attackPower.percent -= 1;
284 +
285 + stats.damage.all += 1;
286 + efficiency.damage = (calculatePower(stats, job, weapon) - defaultPower) / majorPure;
287 + stats.damage.all -= 1;
288 +
289 + stats.criticalDamage += 1;
290 + efficiency.criticalDamage = (calculatePower(stats, job, weapon) - defaultPower) / majorPure;
291 + stats.criticalDamage -= 1;
292 +
293 + // 곱연산
294 + const ignoreGuardSaved = stats.ignoreGuard;
295 + stats.ignoreGuard = (1 - (1 - stats.ignoreGuard / 100) * 0.99) * 100;
296 + efficiency.ignoreGuard = (calculatePower(stats, job, weapon) - defaultPower) / majorPure;
297 + stats.ignoreGuard = ignoreGuardSaved;
298 +
299 + return efficiency;
300 +}
301 +
302 +// 버프 적용 스탯 구하기
303 +const getBuffStats = function(stats, job) {
304 + const jobModel = require('../model/job');
305 + const buff = jobModel[job].stats.active;
306 + const defaultBuff = jobModel.default.stats.active;
307 +
308 + return {
309 + major: {
310 + pure: stats.major.pure + buff.major.pure,
311 + percent: stats.major.percent + buff.major.percent,
312 + added: stats.major.added
313 + },
314 + minor: stats.minor,
315 + damage: {
316 + all: stats.damage.all + buff.damage.all + defaultBuff.damage.all,
317 + boss: stats.damage.boss + buff.damage.boss + defaultBuff.damage.boss
318 + },
319 + finalDamage: stats.finalDamage,
320 + criticalDamage: stats.criticalDamage + buff.criticalDamage + defaultBuff.criticalDamage,
321 + attackPower: {
322 + pure: stats.attackPower.pure + buff.attackPower.pure,
323 + percent: stats.attackPower.percent + buff.attackPower.percent + defaultBuff.attackPower.percent
324 + },
325 + ignoreGuard: (1 - (1 - (stats.ignoreGuard / 100)) * (1 - (buff.ignoreGuard / 100)) * (1 - (defaultBuff.ignoreGuard / 100))) * 100
326 + };
327 +}
328 +
329 +// 크리티컬 데미지, 보스 공격력, 방어율 무시를 반영하여 방어율 300% 몬스터 공격시 데미지 산출 값
330 +const calculatePower = function(stats, job, weapon) {
331 + const jobConst = require('../model/job')[job].jobConst;
332 + const weaponConst = require('../model/weapon')[weapon];
333 + return Math.max(
334 + (
335 + (stats.major.pure * (1 + stats.major.percent / 100) + stats.major.added) * 4 +
336 + stats.minor
337 + ) *
338 + 0.01 *
339 + (stats.attackPower.pure * (1 + stats.attackPower.percent / 100)) *
340 + jobConst *
341 + weaponConst *
342 + (1 + stats.damage.all / 100 + stats.damage.boss / 100) *
343 + (1 + stats.finalDamage / 100) *
344 + (1.2 + stats.criticalDamage / 100) *
345 + (1 - 3 * (1 - stats.ignoreGuard / 100)),
346 + 1);
347 +}
348 +
202 module.exports = { 349 module.exports = {
203 getCharacter: async function(req, res) { 350 getCharacter: async function(req, res) {
204 if (!req.query.nickname) { 351 if (!req.query.nickname) {
...@@ -225,8 +372,21 @@ module.exports = { ...@@ -225,8 +372,21 @@ module.exports = {
225 res.status(403).send(); 372 res.status(403).send();
226 return; 373 return;
227 } 374 }
228 - console.log(analysisEquipment);
229 375
230 - res.send(characterInfo); 376 + const stats = analyzeStats(characterInfo, analysisEquipment);
377 + const buffStats = getBuffStats(stats, characterInfo.character.job);
378 + const efficiency = calculateEfficiency(stats, characterInfo.character.job, analysisEquipment.weapon);
379 + const buffEfficiency = calculateEfficiency(buffStats, characterInfo.character.job, analysisEquipment.weapon);
380 +
381 + res.send({
382 + default: {
383 + stats: stats,
384 + efficiency: efficiency
385 + },
386 + buff: {
387 + stats: buffStats,
388 + efficiency: buffEfficiency
389 + }
390 + });
231 } 391 }
232 }; 392 };
...\ No newline at end of file ...\ No newline at end of file
......