<commit_before>import { PlayerPhase as Phase } from '@karuta/sanguosha-core';

import GameRule from '../../driver/GameRule';
import GameEvent from '../../driver/GameEvent';
import PhaseChange from '../../driver/PhaseChange';
import CardDraw from '../../driver/CardDraw';
import Card from '../../driver/Card';
import ServerPlayer from '../../driver/ServerPlayer';
import CardAction from '../../core/CardAction';

class PhaseRule extends GameRule<PhaseChange> {
	constructor() {
		super(GameEvent.ProceedingPhase);
	}

	isTriggerable(data: PhaseChange): boolean {
		return Boolean(this.driver && data && data.player);
	}

	async effect(data: PhaseChange): Promise<boolean> {
		switch (data.to) {
		case Phase.Draw:
			await this.drawCards(data.player);
			break;
		case Phase.Play:
			await this.play(data.player);
			break;
		case Phase.Discard:
			await this.discardCards(data.player);
			break;
		default:
			break;
		}
		return false;
	}

	async drawCards(player: ServerPlayer): Promise<void> {
		const data = new CardDraw(player, 2);
		const driver = this.getDriver();
		await driver.trigger(GameEvent.DrawingNCards, data);
		await driver.drawCards(player, data.num);
	}

	async play(player: ServerPlayer): Promise<void> {
		const driver = this.getDriver();
		const handArea = player.getHandArea();
		for (;;) {
			player.setUseLimit('strike', 1);
			const cards = handArea.getCards();
			const availableCards: Card[] = [];
			for (const ccard of cards) {
				const card = ccard as Card;
				if (await driver.isCardAvailable(player, card)) {
					availableCards.push(card);
				}
			}

			const action = await player.play(availableCards);
			if (!action) {
				break;<commit_msg>Implement judging phase<commit_after>import { PlayerPhase as Phase } from '@karuta/sanguosha-core';

import Card from '../../driver/Card';
import CardAction from '../../core/CardAction';
import CardDraw from '../../driver/CardDraw';
import DelayedCardEffect from '../../driver/DelayedCardEffect';
import GameEvent from '../../driver/GameEvent';
import GameRule from '../../driver/GameRule';
import PhaseChange from '../../driver/PhaseChange';
import ServerPlayer from '../../driver/ServerPlayer';

class PhaseRule extends GameRule<PhaseChange> {
	constructor() {
		super(GameEvent.ProceedingPhase);
	}

	isTriggerable(data: PhaseChange): boolean {
		return Boolean(this.driver && data && data.player);
	}

	async effect(data: PhaseChange): Promise<boolean> {
		switch (data.to) {
		case Phase.Judge:
			await this.processJudgements(data.player);
			break;
		case Phase.Draw:
			await this.drawCards(data.player);
			break;
		case Phase.Play:
			await this.play(data.player);
			break;
		case Phase.Discard:
			await this.discardCards(data.player);
			break;
		default:
			break;
		}
		return false;
	}

	async processJudgements(player: ServerPlayer): Promise<void> {
		const driver = this.getDriver();
		const judgeArea = player.getJudgeArea();
		const processArea = player.getProcessArea();
		while (judgeArea.size > 0) {
			const meta = judgeArea.first();
			if (!meta) {
				judgeArea.takeFirst();
				continue;
			}

			const card = meta as Card;
			await driver.moveCards([card], processArea, { open: true });

			const effect = new DelayedCardEffect(card, player);
			await driver.takeCardEffect(effect);

			await card.complete(driver);
		}
	}

	async drawCards(player: ServerPlayer): Promise<void> {
		const data = new CardDraw(player, 2);
		const driver = this.getDriver();
		await driver.trigger(GameEvent.DrawingNCards, data);
		await driver.drawCards(player, data.num);
	}

	async play(player: ServerPlayer): Promise<void> {
		const driver = this.getDriver();
		const handArea = player.getHandArea();
		for (;;) {
			player.setUseLimit('strike', 1);
			const cards = handArea.getCards();
			const availableCards: Card[] = [];
			for (const ccard of cards) {
				const card = ccard as Card;
				if (await driver.isCardAvailable(player, card)) {
					availableCards.push(card);
				}
			}

			const action = await player.play(availableCards);
			if (!action) {
				break;
{'fraction_non_alphanumeric': 0.14275166133398967, 'fraction_numerical': 0.0012306177701206006, 'mean_word_length': 3.826603325415677, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7630809', 'n_tokens_mistral': 1414, 'n_tokens_neox': 1262, 'n_words': 314}