feat: 유산 목록에서 로그를 더 가져올 수 있음

This commit is contained in:
2022-06-25 12:22:25 +09:00
parent da2a6f347a
commit 647c2439e3
5 changed files with 325 additions and 255 deletions
@@ -0,0 +1,40 @@
<?php
namespace sammo\API\InheritAction;
use DateTimeInterface;
use sammo\DB;
use sammo\Session;
use sammo\Validator;
use sammo\Util;
class GetMoreLog extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('integer', 'lastID');
if (!$v->validate()) {
return $v->errorStr();
}
$this->args['lastID'] = Util::toInt($this->args['lastID']);
return null;
}
function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$userID = $session->userID;
$lastID = $this->args['lastID'];
$db = DB::db();
$lastInheritPointLogs = $db->query('SELECT id, server_id, year, month, date, text FROM user_record WHERE log_type = %s AND `user_id` = %i AND id < %i ORDER BY id desc LIMIT 30', "inheritPoint", $userID, $lastID);
return [
'result'=> true,
'log' => $lastInheritPointLogs,
];
}
}
+239 -229
View File
@@ -70,7 +70,7 @@
<div class="a-right col-6 align-self-center">유니크 경매</div> <div class="a-right col-6 align-self-center">유니크 경매</div>
<div class="col-6"> <div class="col-6">
<select v-model="specificUnique" class="form-select col-6"> <select v-model="specificUnique" class="form-select col-6">
<option disabled selected :value="null"> 유니크 선택 </option> <option disabled selected :value="null">유니크 선택</option>
<option v-for="(info, key) in availableUnique" :key="key" :value="key"> <option v-for="(info, key) in availableUnique" :key="key" :value="key">
{{ info.title }} {{ info.title }}
</option> </option>
@@ -91,7 +91,7 @@
<small class="form-text text-muted" <small class="form-text text-muted"
>얻고자 하는 유니크 아이템으로 경매를 시작합니다. 24 동안 진행됩니다.<br /> >얻고자 하는 유니크 아이템으로 경매를 시작합니다. 24 동안 진행됩니다.<br />
<!-- eslint-disable-next-line vue/no-v-html --> <!-- eslint-disable-next-line vue/no-v-html -->
<span style="color: white" v-html="specificUnique == null?'':availableUnique[specificUnique].info" /> <span style="color: white" v-html="specificUnique == null ? '' : availableUnique[specificUnique].info" />
</small> </small>
</div> </div>
@@ -185,10 +185,10 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="bg1 a-center">유산 포인트 변경 내역(최근 30)</div> <div class="bg1 a-center">유산 포인트 변경 내역</div>
</div> </div>
</div> </div>
<div v-for="(log, idx) in lastInheritPointLogs" :key="idx" class="row"> <div v-for="[idx, log] of inheritPointLogs" :key="idx" class="row">
<div class="col a-right" style="max-width: 20ch"> <div class="col a-right" style="max-width: 20ch">
<small class="text-muted tnum">[{{ log.date }}]</small> <small class="text-muted tnum">[{{ log.date }}]</small>
</div> </div>
@@ -196,21 +196,11 @@
{{ log.text }} {{ log.text }}
</div> </div>
</div> </div>
<div class="d-grid"><BButton @click="getMoreLog()"> 가져오기</BButton></div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from "vue";
import "@scss/common/bootstrap5.scss";
import "@scss/game_bg.scss";
import TopBackBar from "@/components/TopBackBar.vue";
import _ from "lodash";
import NumberInputWithInfo from "@/components/NumberInputWithInfo.vue";
import { SammoAPI } from "./SammoAPI";
import type { inheritBuffType } from "./defs/API/InheritAction";
import * as JosaUtil from '@/util/JosaUtil';
import { BButton } from "bootstrap-vue-3";
type InheritanceType = type InheritanceType =
| "previous" | "previous"
| "lived_month" | "lived_month"
@@ -227,15 +217,53 @@ type InheritanceType =
type InheritanceViewType = InheritanceType | "sum" | "new"; type InheritanceViewType = InheritanceType | "sum" | "new";
declare const lastInheritPointLogs: { declare const staticValues: {
server_id: string; lastInheritPointLogs: InheritPointLogItem[];
year: number; items: Record<InheritanceType, number>;
month: number; currentInheritBuff: {
date: string; [v in inheritBuffType]: number | undefined;
text: string; };
}[]; maxInheritBuff: number;
inheritActionCost: {
buff: number[];
resetTurnTime: number;
resetSpecialWar: number;
randomUnique: number;
nextSpecial: number;
minSpecificUnique: number;
};
resetTurnTimeLevel: number;
resetSpecialWarLevel: number;
declare const items: Record<InheritanceType, number>; availableSpecialWar: Record<
string,
{
title: string;
info: string;
}
>;
availableUnique: Record<
string,
{
title: string;
rawName: string;
info: string;
}
>;
};
</script>
<script lang="ts" setup>
import { reactive, ref } from "vue";
import "@scss/common/bootstrap5.scss";
import "@scss/game_bg.scss";
import TopBackBar from "@/components/TopBackBar.vue";
import _ from "lodash";
import NumberInputWithInfo from "@/components/NumberInputWithInfo.vue";
import { SammoAPI } from "./SammoAPI";
import type { inheritBuffType, InheritPointLogItem } from "./defs/API/InheritAction";
import * as JosaUtil from "@/util/JosaUtil";
import { BButton } from "bootstrap-vue-3";
import { unwrap } from "./util/unwrap";
const inheritanceViewText: Record<InheritanceViewType, { title: string; info: string }> = { const inheritanceViewText: Record<InheritanceViewType, { title: string; info: string }> = {
sum: { sum: {
@@ -296,11 +324,6 @@ const inheritanceViewText: Record<InheritanceViewType, { title: string; info: st
}, },
}; };
declare const currentInheritBuff: {
[v in inheritBuffType]: number | undefined;
};
const inheritBuffHelpText: Record< const inheritBuffHelpText: Record<
inheritBuffType, inheritBuffType,
{ {
@@ -342,226 +365,213 @@ const inheritBuffHelpText: Record<
}, },
}; };
declare const maxInheritBuff: number; const inheritBuff = reactive({} as Record<inheritBuffType, number>);
declare const inheritActionCost: { for (const buffKey of Object.keys(inheritBuffHelpText) as inheritBuffType[]) {
buff: number[]; inheritBuff[buffKey] = staticValues.currentInheritBuff[buffKey] ?? 0;
resetTurnTime: number; }
resetSpecialWar: number;
randomUnique: number;
nextSpecial: number;
minSpecificUnique: number;
};
declare const resetTurnTimeLevel: number; const title = "유산 관리";
declare const resetSpecialWarLevel: number;
declare const availableSpecialWar: Record< const items = ref(
string, (() => {
{ const totalPoint = Math.floor(_.sum(Object.values(staticValues.items)));
title: string; const previousPoint = Math.floor(staticValues.items["previous"]);
info: string; const newPoint = Math.floor(totalPoint - previousPoint);
} const result: Record<InheritanceViewType, number> = {
>; ...staticValues.items,
sum: totalPoint,
declare const availableUnique: Record< new: newPoint,
string,
{
title: string;
rawName: string;
info: string;
}
>;
export default defineComponent({
name: "PageInheritPoint",
components: {
TopBackBar,
NumberInputWithInfo,
BButton,
},
data() {
const inheritBuff = {} as Record<inheritBuffType, number>;
for (const buffKey of Object.keys(inheritBuffHelpText) as inheritBuffType[]) {
inheritBuff[buffKey] = currentInheritBuff[buffKey] ?? 0;
}
return {
title: "유산 관리",
inheritanceViewText,
items: (() => {
const totalPoint = Math.floor(_.sum(Object.values(items)));
const previousPoint = Math.floor(items["previous"]);
const newPoint = Math.floor(totalPoint - previousPoint);
const result: Record<InheritanceViewType, number> = {
...items,
sum: totalPoint,
new: newPoint,
};
return result;
})(),
inheritBuffHelpText,
inheritBuff,
prevInheritBuff: currentInheritBuff,
maxInheritBuff,
inheritActionCost,
resetTurnTimeLevel,
resetSpecialWarLevel,
nextSpecialWar: Object.keys(availableSpecialWar)[0],
specificUnique: null,
availableSpecialWar,
availableUnique,
specificUniqueAmount: inheritActionCost.minSpecificUnique,
lastInheritPointLogs,
}; };
}, return result;
methods: { })()
async buyInheritBuff(buffKey: inheritBuffType) { );
const level = Math.floor(this.inheritBuff[buffKey]);
const prevLevel = this.prevInheritBuff[buffKey] ?? 0;
if (level == prevLevel) {
return;
}
if (level < prevLevel) {
alert("낮출 수 없습니다.");
return;
}
const cost = this.inheritActionCost.buff[level] - this.inheritActionCost.buff[prevLevel];
if (this.items.previous < cost) {
alert("유산 포인트가 부족합니다.");
return;
}
const name = inheritBuffHelpText[buffKey].title; const {
const josaUl = JosaUtil.pick(name, '을'); maxInheritBuff,
if (!confirm(`${name}${josaUl} ${level}등급으로 올릴까요? ${cost} 포인트가 소모됩니다.`)) { inheritActionCost,
return; currentInheritBuff: prevInheritBuff,
} availableSpecialWar,
availableUnique,
} = staticValues;
try { const nextSpecialWar = ref(Object.keys(availableSpecialWar)[0]);
await SammoAPI.InheritAction.BuyHiddenBuff({ const specificUnique = ref<string | null>(null);
type: buffKey, const specificUniqueAmount = ref(inheritActionCost.minSpecificUnique);
level,
});
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert("성공했습니다."); const lastLogID = ref(Math.min(...staticValues.lastInheritPointLogs.map((v) => v.id)));
//TODO: 페이지 새로고침 필요없이 하도록 const inheritPointLogs = ref(
location.reload(); (() => {
}, const logs = new Map<number, InheritPointLogItem>();
async buySimple(type: "ResetTurnTime" | "BuyRandomUnique" | "ResetSpecialWar") { for (const log of staticValues.lastInheritPointLogs) {
const costMap: Record<typeof type, number> = { logs.set(log.id, log);
ResetTurnTime: inheritActionCost.resetTurnTime, }
ResetSpecialWar: inheritActionCost.resetSpecialWar, return logs;
BuyRandomUnique: inheritActionCost.randomUnique, })()
}; );
const cost = costMap[type]; staticValues.lastInheritPointLogs;
if (cost === undefined) { async function buyInheritBuff(buffKey: inheritBuffType) {
alert(`올바르지 않은 타입:${type}`); const level = Math.floor(unwrap(inheritBuff[buffKey]));
return; const prevLevel = prevInheritBuff[buffKey] ?? 0;
} if (level == prevLevel) {
return;
}
if (level < prevLevel) {
alert("낮출 수 없습니다.");
return;
}
const cost = inheritActionCost.buff[level] - inheritActionCost.buff[prevLevel];
if (items.value.previous < cost) {
alert("유산 포인트가 부족합니다.");
return;
}
const messageMap: Record<typeof type, string> = { const name = inheritBuffHelpText[buffKey].title;
ResetTurnTime: `${cost} 포인트로 턴을 초기화 하시겠습니까?`, const josaUl = JosaUtil.pick(name, "을");
ResetSpecialWar: `${cost} 포인트로 전투 특기를 초기화 하시겠습니까?`, if (!confirm(`${name}${josaUl} ${level}등급으로 올릴까요? ${cost} 포인트가 소모됩니다.`)) {
BuyRandomUnique: `${cost} 포인트로 랜덤 유니크를 구입하시겠습니까?`, return;
}; }
if (this.items.previous < cost) {
alert("유산 포인트가 부족합니다.");
return;
}
if (!confirm(messageMap[type])) {
return;
}
try { try {
await SammoAPI.InheritAction[type](); await SammoAPI.InheritAction.BuyHiddenBuff({
} catch (e) { type: buffKey,
console.error(e); level,
alert(`실패했습니다: ${e}`); });
return; } catch (e) {
} console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert("성공했습니다."); alert("성공했습니다.");
//TODO: 페이지 새로고침 필요없이 하도록 //TODO: 페이지 새로고침 필요없이 하도록
location.reload(); location.reload();
}, }
async setNextSpecialWar() { async function buySimple(type: "ResetTurnTime" | "BuyRandomUnique" | "ResetSpecialWar") {
const specialWarName = this.availableSpecialWar[this.nextSpecialWar].title ?? undefined; const costMap: Record<typeof type, number> = {
if (specialWarName === undefined) { ResetTurnTime: inheritActionCost.resetTurnTime,
alert(`잘못된 타입: ${this.nextSpecialWar}`); ResetSpecialWar: inheritActionCost.resetSpecialWar,
return; BuyRandomUnique: inheritActionCost.randomUnique,
} };
const cost = inheritActionCost.nextSpecial; const cost = costMap[type];
if (this.items.previous < cost) { if (cost === undefined) {
alert("유산 포인트가 부족합니다."); alert(`올바르지 않은 타입:${type}`);
return; return;
} }
const josaRo = JosaUtil.pick(specialWarName, '로'); const messageMap: Record<typeof type, string> = {
if (!confirm(`${cost} 포인트로 다음 전특을 ${specialWarName}${josaRo} 고정하겠습니까?`)) { ResetTurnTime: `${cost} 포인트로 턴을 초기화 하시겠습니까?`,
return; ResetSpecialWar: `${cost} 포인트로 전투 특기를 초기화 하시겠습니까?`,
} BuyRandomUnique: `${cost} 포인트로 랜덤 유니크를 구입하시겠습니까?`,
};
if (items.value.previous < cost) {
alert("유산 포인트가 부족합니다.");
return;
}
if (!confirm(messageMap[type])) {
return;
}
try { try {
await SammoAPI.InheritAction.SetNextSpecialWar({ await SammoAPI.InheritAction[type]();
type: this.nextSpecialWar, } catch (e) {
}); console.error(e);
} catch (e) { alert(`실패했습니다: ${e}`);
console.error(e); return;
alert(`실패했습니다: ${e}`); }
return;
}
alert("성공했습니다."); alert("성공했습니다.");
//TODO: 페이지 새로고침 필요없이 하도록 //TODO: 페이지 새로고침 필요없이 하도록
location.reload(); location.reload();
}, }
async openUniqueItemAuction() { async function setNextSpecialWar() {
if(this.specificUnique === null){ const specialWarName = availableSpecialWar[nextSpecialWar.value].title ?? undefined;
alert("유니크를 선택해주세요."); if (specialWarName === undefined) {
return; alert(`잘못된 타입: ${nextSpecialWar.value}`);
} return;
}
const uniqueName = this.availableUnique[this.specificUnique].title ?? undefined; const cost = inheritActionCost.nextSpecial;
if (uniqueName === undefined) { if (items.value.previous < cost) {
alert(`잘못된 타입: ${this.specificUnique}`); alert("유산 포인트가 부족합니다.");
return; return;
} }
const uniqueRawName = this.availableUnique[this.specificUnique].rawName ?? undefined;
const amount = this.specificUniqueAmount; const josaRo = JosaUtil.pick(specialWarName, "로");
if (this.items.previous < amount) { if (!confirm(`${cost} 포인트로 다음 전특을 ${specialWarName}${josaRo} 고정하겠습니까?`)) {
alert("유산 포인트가 부족합니다."); return;
return; }
}
const josaUl = JosaUtil.pick(uniqueRawName, '을'); try {
if (!confirm(`${amount} 포인트로 ${uniqueName}${josaUl} 입찰하겠습니까?`)) { await SammoAPI.InheritAction.SetNextSpecialWar({
return; type: nextSpecialWar.value,
} });
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
try { alert("성공했습니다.");
await SammoAPI.Auction.OpenUniqueAuction({ //TODO: 페이지 새로고침 필요없이 하도록
itemID: this.specificUnique, location.reload();
amount, }
}); async function openUniqueItemAuction() {
} catch (e) { if (specificUnique.value === null) {
console.error(e); alert("유니크를 선택해주세요.");
alert(`실패했습니다: ${e}`); return;
return; }
}
alert("성공했습니다. 경매장을 확인해주세요."); const uniqueName = availableUnique[specificUnique.value].title ?? undefined;
//TODO: 페이지 새로고침 필요없이 하도록 if (uniqueName === undefined) {
location.reload(); alert(`잘못된 타입: ${specificUnique.value}`);
}, return;
}, }
}); const uniqueRawName = availableUnique[specificUnique.value].rawName ?? undefined;
const amount = specificUniqueAmount.value;
if (items.value.previous < amount) {
alert("유산 포인트가 부족합니다.");
return;
}
const josaUl = JosaUtil.pick(uniqueRawName, "을");
if (!confirm(`${amount} 포인트로 ${uniqueName}${josaUl} 입찰하겠습니까?`)) {
return;
}
try {
await SammoAPI.Auction.OpenUniqueAuction({
itemID: specificUnique.value,
amount,
});
} catch (e) {
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
alert("성공했습니다. 경매장을 확인해주세요.");
//TODO: 페이지 새로고침 필요없이 하도록
location.reload();
}
async function getMoreLog(): Promise<void>{
try{
const result = await SammoAPI.InheritAction.GetMoreLog({
lastID: lastLogID.value
});
for(const log of result.log){
inheritPointLogs.value.set(log.id, log);
lastLogID.value = Math.min(lastLogID.value, log.id);
}
}catch(e){
console.error(e);
alert(`실패했습니다: ${e}`);
return;
}
}
</script> </script>
<style> <style>
+4 -1
View File
@@ -17,7 +17,7 @@ import { APIPathGen, NumVar, StrVar } from "./util/APIPathGen.js";
import type { BettingDetailResponse, BettingListResponse } from "./defs/API/Betting"; import type { BettingDetailResponse, BettingListResponse } from "./defs/API/Betting";
import type { ReserveBulkCommandResponse, ReserveCommandResponse, ReservedCommandResponse } from "./defs/API/Command"; import type { ReserveBulkCommandResponse, ReserveCommandResponse, ReservedCommandResponse } from "./defs/API/Command";
import type { ChiefResponse } from "./defs/API/NationCommand"; import type { ChiefResponse } from "./defs/API/NationCommand";
import type { inheritBuffType } from "./defs/API/InheritAction"; import type { inheritBuffType, InheritLogResponse } from "./defs/API/InheritAction";
import type { SetBlockWarResponse, GeneralListResponse as NationGeneralListResponse } from "./defs/API/Nation"; import type { SetBlockWarResponse, GeneralListResponse as NationGeneralListResponse } from "./defs/API/Nation";
import type { UploadImageResponse } from "./defs/API/Misc"; import type { UploadImageResponse } from "./defs/API/Misc";
import type { GeneralLogType, GetGeneralLogResponse, JoinArgs } from "./defs/API/General"; import type { GeneralLogType, GetGeneralLogResponse, JoinArgs } from "./defs/API/General";
@@ -154,6 +154,9 @@ const apiRealPath = {
SetNextSpecialWar: PUT as APICallT<{ SetNextSpecialWar: PUT as APICallT<{
type: string; type: string;
}>, }>,
GetMoreLog: GET as APICallT<{
lastID: number
}, InheritLogResponse>
}, },
Misc: { Misc: {
UploadImage: POST as APICallT< UploadImage: POST as APICallT<
+23 -8
View File
@@ -1,9 +1,24 @@
import type { ValidResponse } from "@/util/callSammoAPI";
export type inheritBuffType = export type inheritBuffType =
| "warAvoidRatio" | "warAvoidRatio"
| "warCriticalRatio" | "warCriticalRatio"
| "warMagicTrialProb" | "warMagicTrialProb"
| "domesticSuccessProb" | "domesticSuccessProb"
| "domesticFailProb" | "domesticFailProb"
| "warAvoidRatioOppose" | "warAvoidRatioOppose"
| "warCriticalRatioOppose" | "warCriticalRatioOppose"
| "warMagicTrialProbOppose"; | "warMagicTrialProbOppose";
export type InheritPointLogItem = {
id: number;
server_id: string;
year: number;
month: number;
date: string;
text: string;
};
export type InheritLogResponse = ValidResponse & {
log: InheritPointLogItem[];
};
+19 -17
View File
@@ -68,7 +68,7 @@ foreach (InheritanceKey::cases() as $key) {
$resetTurnTimeLevel = ($me->getAuxVar('inheritResetTurnTime') ?? -1) + 1; $resetTurnTimeLevel = ($me->getAuxVar('inheritResetTurnTime') ?? -1) + 1;
$resetSpecialWarLevel = ($me->getAuxVar('inheritResetSpecialWar') ?? -1) + 1; $resetSpecialWarLevel = ($me->getAuxVar('inheritResetSpecialWar') ?? -1) + 1;
$lastInheritPointLogs = $db->query('SELECT server_id, year, month, date, text FROM user_record WHERE log_type = %s AND user_id = %i ORDER BY id desc LIMIT 30', "inheritPoint", $userID); $lastInheritPointLogs = $db->query('SELECT id, server_id, year, month, date, text FROM user_record WHERE log_type = %s AND user_id = %i ORDER BY id desc LIMIT 30', "inheritPoint", $userID);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@@ -81,22 +81,24 @@ $lastInheritPointLogs = $db->query('SELECT server_id, year, month, date, text FR
<?= WebUtil::printJS('../d_shared/common_path.js', true) ?> <?= WebUtil::printJS('../d_shared/common_path.js', true) ?>
<?= WebUtil::printDist('vue', 'v_inheritPoint', true) ?> <?= WebUtil::printDist('vue', 'v_inheritPoint', true) ?>
<?= WebUtil::printStaticValues([ <?= WebUtil::printStaticValues([
'items' => $items, 'staticValues' => [
'currentInheritBuff' => $currentInheritBuff, 'items' => $items,
'maxInheritBuff' => TriggerInheritBuff::MAX_STEP, 'currentInheritBuff' => $currentInheritBuff,
'resetTurnTimeLevel' => $resetTurnTimeLevel, 'maxInheritBuff' => TriggerInheritBuff::MAX_STEP,
'resetSpecialWarLevel' => $resetSpecialWarLevel, 'resetTurnTimeLevel' => $resetTurnTimeLevel,
'inheritActionCost' => [ 'resetSpecialWarLevel' => $resetSpecialWarLevel,
'buff' => GameConst::$inheritBuffPoints, 'inheritActionCost' => [
'resetTurnTime' => calcResetAttrPoint($resetTurnTimeLevel), 'buff' => GameConst::$inheritBuffPoints,
'resetSpecialWar' => calcResetAttrPoint($resetSpecialWarLevel), 'resetTurnTime' => calcResetAttrPoint($resetTurnTimeLevel),
'randomUnique' => GameConst::$inheritItemRandomPoint, 'resetSpecialWar' => calcResetAttrPoint($resetSpecialWarLevel),
'nextSpecial' => GameConst::$inheritSpecificSpecialPoint, 'randomUnique' => GameConst::$inheritItemRandomPoint,
'minSpecificUnique' => GameConst::$inheritItemUniqueMinPoint, 'nextSpecial' => GameConst::$inheritSpecificSpecialPoint,
], 'minSpecificUnique' => GameConst::$inheritItemUniqueMinPoint,
'availableSpecialWar' => $avilableSpecialWar, ],
'availableUnique' => $availableUnique, 'availableSpecialWar' => $avilableSpecialWar,
'lastInheritPointLogs' => $lastInheritPointLogs, 'availableUnique' => $availableUnique,
'lastInheritPointLogs' => $lastInheritPointLogs,
]
]) ?> ]) ?>
</head> </head>