麻雀が動作できるように (#15815)

This commit is contained in:
Take-John 2025-04-13 18:29:56 +09:00 committed by GitHub
parent 7f9c84ebe8
commit 7d9a6a3f9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 69 additions and 47 deletions

View File

@ -288,6 +288,12 @@ export * as 'invite/create' from './endpoints/invite/create.js';
export * as 'invite/delete' from './endpoints/invite/delete.js'; export * as 'invite/delete' from './endpoints/invite/delete.js';
export * as 'invite/limit' from './endpoints/invite/limit.js'; export * as 'invite/limit' from './endpoints/invite/limit.js';
export * as 'invite/list' from './endpoints/invite/list.js'; export * as 'invite/list' from './endpoints/invite/list.js';
export * as 'mahjong/cancel-match' from './endpoints/mahjong/cancel-match.js';
export * as 'mahjong/create-room' from './endpoints/mahjong/create-room.js';
export * as 'mahjong/games' from './endpoints/mahjong/games.js';
export * as 'mahjong/join-room' from './endpoints/mahjong/join-room.js';
export * as 'mahjong/show-room' from './endpoints/mahjong/show-room.js';
export * as 'mahjong/verify' from './endpoints/mahjong/verify.js';
export * as 'meta' from './endpoints/meta.js'; export * as 'meta' from './endpoints/meta.js';
export * as 'miauth/gen-token' from './endpoints/miauth/gen-token.js'; export * as 'miauth/gen-token' from './endpoints/miauth/gen-token.js';
export * as 'mute/create' from './endpoints/mute/create.js'; export * as 'mute/create' from './endpoints/mute/create.js';

View File

@ -24,18 +24,18 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onDeactivated, onMounted, onUnmounted, ref } from 'vue'; import { computed, onDeactivated, onMounted, onUnmounted, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { misskeyApi } from '@/scripts/misskey-api.js'; import { useInterval } from '@@/js/use-interval.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { misskeyApi } from '@/utility/misskey-api.js';
import { definePage } from '@/page.js';
import { useStream } from '@/stream.js'; import { useStream } from '@/stream.js';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { $i } from '@/account.js'; import { $i } from '@/i.js';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import { useRouter } from '@/router/supplier.js'; import { useRouter } from '@/router.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { useInterval } from '@/scripts/use-interval.js'; import * as sound from '@/utility/sound.js';
import * as sound from '@/scripts/sound.js';
const myGamesPagination = { const myGamesPagination = {
endpoint: 'mahjong/games' as const, endpoint: 'mahjong/games' as const,
@ -74,7 +74,7 @@ async function createRoom(ev: MouseEvent) {
router.push(`/mahjong/g/${room.id}`); router.push(`/mahjong/g/${room.id}`);
} }
definePageMetadata(computed(() => ({ definePage(computed(() => ({
title: i18n.ts._mahjong.mahjong, title: i18n.ts._mahjong.mahjong,
icon: 'ti ti-device-gamepad', icon: 'ti ti-device-gamepad',
}))); })));

View File

@ -277,21 +277,21 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, onActivated, onDeactivated, onMounted, onUnmounted, reactive, ref, shallowRef, triggerRef, watch } from 'vue'; import { computed, onActivated, onDeactivated, onMounted, onUnmounted, reactive, ref, shallowRef, triggerRef, watch } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import * as Mmj from 'misskey-mahjong'; import * as Mmj from 'misskey-mahjong';
import { useInterval } from '@@/js/use-interval.js';
import XTile from './tile.vue'; import XTile from './tile.vue';
import XHuro from './huro.vue'; import XHuro from './huro.vue';
import XHandTiles from './hand-tiles.vue'; import XHandTiles from './hand-tiles.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import MkSwitch from '@/components/MkSwitch.vue'; import MkSwitch from '@/components/MkSwitch.vue';
import { deepClone } from '@/scripts/clone.js'; import { deepClone } from '@/utility/clone.js';
import { useInterval } from '@/scripts/use-interval.js'; import { ensureSignin } from '@/i.js';
import { signinRequired } from '@/account.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { misskeyApi } from '@/scripts/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
import { userPage } from '@/filters/user.js'; import { userPage } from '@/filters/user.js';
import * as sound from '@/scripts/sound.js'; import * as sound from '@/utility/sound.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { confetti } from '@/scripts/confetti.js'; import { confetti } from '@/utility/confetti.js';
//#region syntax suger //#region syntax suger
function mj$(tid: Mmj.TileId): Mmj.TileInstance { function mj$(tid: Mmj.TileId): Mmj.TileInstance {
@ -303,7 +303,7 @@ function mj$type(tid: Mmj.TileId): Mmj.TileType {
} }
//#endregion //#endregion
const $i = signinRequired(); const $i = ensureSignin();
const props = defineProps<{ const props = defineProps<{
room: Misskey.entities.MahjongRoomDetailed; room: Misskey.entities.MahjongRoomDetailed;

View File

@ -52,18 +52,18 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, watch, ref, onMounted, shallowRef, onUnmounted } from 'vue'; import { computed, watch, ref, onMounted, shallowRef, onUnmounted } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import * as Mmj from 'misskey-mahjong'; import * as Mmj from 'misskey-mahjong';
import type { MenuItem } from '@/types/menu.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { signinRequired } from '@/account.js'; import { ensureSignin } from '@/i.js';
import { deepClone } from '@/scripts/clone.js'; import { deepClone } from '@/utility/clone.js';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import MkRadios from '@/components/MkRadios.vue'; import MkRadios from '@/components/MkRadios.vue';
import MkSwitch from '@/components/MkSwitch.vue'; import MkSwitch from '@/components/MkSwitch.vue';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { MenuItem } from '@/types/menu.js'; import { useRouter } from '@/router.js';
import { useRouter } from '@/router/supplier.js';
const $i = signinRequired(); const $i = ensureSignin();
const router = useRouter(); const router = useRouter();

View File

@ -12,18 +12,18 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, watch, ref, onMounted, shallowRef, onUnmounted } from 'vue'; import { computed, watch, ref, onMounted, shallowRef, onUnmounted } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { useInterval } from '@@/js/use-interval.js';
import RoomSetting from './room.setting.vue'; import RoomSetting from './room.setting.vue';
import RoomGame from './room.game.vue'; import RoomGame from './room.game.vue';
import { misskeyApi } from '@/scripts/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { definePage } from '@/page.js';
import { useStream } from '@/stream.js'; import { useStream } from '@/stream.js';
import { signinRequired } from '@/account.js'; import { ensureSignin } from '@/i.js';
import { useRouter } from '@/router/supplier.js'; import { useRouter } from '@/router.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { useInterval } from '@/scripts/use-interval.js';
const $i = signinRequired(); const $i = ensureSignin();
const router = useRouter(); const router = useRouter();
@ -106,7 +106,7 @@ onUnmounted(() => {
} }
}); });
definePageMetadata(computed(() => ({ definePage(computed(() => ({
title: i18n.ts._mahjong.mahjong, title: i18n.ts._mahjong.mahjong,
icon: 'ti ti-device-roompad', icon: 'ti ti-device-roompad',
}))); })));

View File

@ -74,20 +74,28 @@ type YakumanName = typeof YAKUMAN_NAMES[number];
export type YakuName = NormalYakuName | YakumanName; export type YakuName = NormalYakuName | YakumanName;
export type HuroForCalcYaku = { type Pon = {
type: 'pon'; type: 'pon';
tile: TileType; tile: TileType;
} | { };
type Cii = {
type: 'cii'; type: 'cii';
tiles: [TileType, TileType, TileType]; tiles: [TileType, TileType, TileType];
} | { };
type Ankan = {
type: 'ankan'; type: 'ankan';
tile: TileType; tile: TileType;
} | { };
type Minkan = {
type: 'minkan'; type: 'minkan';
tile: TileType; tile: TileType;
}; };
export type HuroForCalcYaku = Pon | Cii | Ankan | Minkan;
export type EnvForCalcYaku = { export type EnvForCalcYaku = {
/** /**
* () * ()
@ -604,7 +612,7 @@ new SeatWind('seat-wind-n', 'n'),
if (fourMentsuOneJyantou == null) return false; if (fourMentsuOneJyantou == null) return false;
const shuntsus = fourMentsuOneJyantou.mentsus.filter(tiles => isShuntu(tiles)); const shuntsus = fourMentsuOneJyantou.mentsus.filter(tiles => isShuntu(tiles));
shuntsus.push(...state.huros.filter(huro => huro.type == 'cii').map(huro => huro.tiles)); shuntsus.push(...state.huros.filter((huro): huro is Cii => huro.type == 'cii').map(huro => huro.tiles));
if (shuntsus.some(tiles => tiles[0] === 'm1' && tiles[1] === 'm2' && tiles[2] === 'm3')) { if (shuntsus.some(tiles => tiles[0] === 'm1' && tiles[1] === 'm2' && tiles[2] === 'm3')) {
if (shuntsus.some(tiles => tiles[0] === 'm4' && tiles[1] === 'm5' && tiles[2] === 'm6')) { if (shuntsus.some(tiles => tiles[0] === 'm4' && tiles[1] === 'm5' && tiles[2] === 'm6')) {

View File

@ -997,19 +997,19 @@ export class MasterGameEngine {
} }
public calcCrc32ForUser1(): number { public calcCrc32ForUser1(): number {
// TODO throw new Error('TODO');
} }
public calcCrc32ForUser2(): number { public calcCrc32ForUser2(): number {
// TODO throw new Error('TODO');
} }
public calcCrc32ForUser3(): number { public calcCrc32ForUser3(): number {
// TODO throw new Error('TODO');
} }
public calcCrc32ForUser4(): number { public calcCrc32ForUser4(): number {
// TODO throw new Error('TODO');
} }
public getState(): MasterState { public getState(): MasterState {
@ -1018,5 +1018,5 @@ export class MasterGameEngine {
} }
function commit_dahai(state: MasterState): MasterState { function commit_dahai(state: MasterState): MasterState {
throw new Error('Not implemented');
} }

View File

@ -5,16 +5,22 @@
import { TileType } from './common.js'; import { TileType } from './common.js';
export type Player = 1 | 2 | 3 | 4;
export type Operation = 'dahai';
export type OperationCode = 1;
export type Log = { export type Log = {
time: number; time: number;
player: 1 | 2 | 3 | 4; player: Player;
operation: 'dahai'; operation: Operation;
tile: string; tile: TileType;
}; };
export type SerializedLog = number[]; export type SerializedLog = [number, Player, OperationCode, TileCode];
export const TILE_MAP: Record<TileType, number> = { export const TILE_MAP = {
'm1': 1, 'm1': 1,
'm2': 2, 'm2': 2,
'm3': 3, 'm3': 3,
@ -49,9 +55,11 @@ export const TILE_MAP: Record<TileType, number> = {
'haku': 32, 'haku': 32,
'hatsu': 33, 'hatsu': 33,
'chun': 34, 'chun': 34,
}; } as const;
export function serializeTile(tile: TileType): number { export type TileCode = typeof TILE_MAP extends Record<string, infer T> ? T : never;
export function serializeTile(tile: TileType): TileCode {
return TILE_MAP[tile]; return TILE_MAP[tile];
} }
@ -59,8 +67,8 @@ export function deserializeTile(tile: number): TileType {
return Object.keys(TILE_MAP).find(key => TILE_MAP[key as TileType] === tile) as TileType; return Object.keys(TILE_MAP).find(key => TILE_MAP[key as TileType] === tile) as TileType;
} }
export function serializeLogs(logs: Log[]) { export function serializeLogs(logs: Log[]): SerializedLog[] {
const _logs: number[][] = []; const _logs: SerializedLog[] = [];
for (let i = 0; i < logs.length; i++) { for (let i = 0; i < logs.length; i++) {
const log = logs[i]; const log = logs[i];
@ -79,7 +87,7 @@ export function serializeLogs(logs: Log[]) {
return _logs; return _logs;
} }
export function deserializeLogs(logs: SerializedLog[]) { export function deserializeLogs(logs: SerializedLog[]): Log[] {
const _logs: Log[] = []; const _logs: Log[] = [];
let time = 0; let time = 0;
@ -97,7 +105,7 @@ export function deserializeLogs(logs: SerializedLog[]) {
time, time,
player: player, player: player,
operation: 'dahai', operation: 'dahai',
tile: log[3], tile: deserializeTile(log[3]),
}); });
break; break;
//case 1: //case 1: