| @@ -4,6 +4,7 @@ import math | |||
| import os | |||
| import random | |||
| import sys | |||
| import wave | |||
| from datetime import datetime, timedelta | |||
| from enum import Enum, auto | |||
| from typing import Callable, TypedDict | |||
| @@ -24,10 +25,12 @@ from pygame.time import Clock | |||
| from pytchat.core.pytchat import PytchatCore | |||
| from pytchat.processors.default.processor import Chat | |||
| from aques import Aques | |||
| from common_module import CommonModule | |||
| from nizika_ai.config import DB | |||
| from nizika_ai.consts import (AnswerType, Character, GPTModel, Platform, | |||
| QueryType) | |||
| from nizika_ai.models import Answer, AnsweredFlag, Query, User | |||
| from nizika_ai.consts import AnswerType, Character, GPTModel, Platform, QueryType | |||
| pygame.init () | |||
| @@ -42,12 +45,11 @@ def main ( | |||
| ) -> None: | |||
| game = Game () | |||
| Bg (game) | |||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||
| Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) | |||
| balloon = Balloon (game) | |||
| deerjika = Deerjika (game, DeerjikaPattern.RELAXED, | |||
| x = CWindow.WIDTH * 3 / 4, | |||
| y = CWindow.HEIGHT - 120, | |||
| balloon = balloon) | |||
| CurrentTime (game, SYSTEM_FONT) | |||
| broadcast = Broadcast (os.environ['BROADCAST_CODE']) | |||
| try: | |||
| @@ -60,6 +62,7 @@ def main ( | |||
| pygame.quit () | |||
| sys.exit () | |||
| if not balloon.enabled: | |||
| DB.begin_transaction () | |||
| answer_flags = (AnsweredFlag.where ('platform', Platform.YOUTUBE.value) | |||
| .where ('answered', False) | |||
| .get ()) | |||
| @@ -68,9 +71,10 @@ def main ( | |||
| answer = Answer.find (answer_flag.answer_id) | |||
| if answer.answer_type == AnswerType.YOUTUBE_REPLY.value: | |||
| query = Query.find (answer.query_id) | |||
| balloon.talk (query.content, answer.content) | |||
| deerjika.talk (query.content, answer.content) | |||
| answer_flag.answered = True | |||
| answer_flag.save () | |||
| DB.commit () | |||
| add_query (broadcast) | |||
| game.redraw () | |||
| @@ -297,7 +301,16 @@ class BgGrass (GameObject): | |||
| super ().redraw () | |||
| class Deerjika (GameObject): | |||
| class Creature (GameObject): | |||
| sound: Sound | |||
| def bell ( | |||
| self, | |||
| ) -> None: | |||
| self.sound.play () | |||
| class Deerjika (Creature): | |||
| """ | |||
| 伊地知ニジカ | |||
| @@ -309,9 +322,12 @@ class Deerjika (GameObject): | |||
| """ | |||
| height: int | |||
| scale: float = .8 | |||
| scale: float = .8 | |||
| surfaces: list[Surface] | |||
| width: int | |||
| talking: bool = False | |||
| wav: bytearray | None = None | |||
| balloon: Balloon | |||
| def __init__ ( | |||
| self, | |||
| @@ -321,10 +337,14 @@ class Deerjika (GameObject): | |||
| layer: int | None = None, | |||
| x: float = 0, | |||
| y: float = 0, | |||
| balloon: Balloon | None = None, | |||
| ): | |||
| if balloon is None: | |||
| raise Exception | |||
| super ().__init__ (game, layer, x = x, y = y) | |||
| self.pattern = pattern | |||
| self.direction = direction | |||
| self.balloon = balloon | |||
| match pattern: | |||
| case DeerjikaPattern.NORMAL: | |||
| ... | |||
| @@ -340,6 +360,7 @@ class Deerjika (GameObject): | |||
| surface.subsurface (x, 0, self.width, self.height)) | |||
| case Direction.RIGHT: | |||
| ... | |||
| self.sound = Sound ('assets/noon.wav') | |||
| def redraw ( | |||
| self, | |||
| @@ -348,9 +369,44 @@ class Deerjika (GameObject): | |||
| (self.width * self.scale, self.height * self.scale)) | |||
| self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y))) | |||
| super ().redraw () | |||
| self.x = random.randrange (CWindow.WIDTH) | |||
| self.y = random.randrange (CWindow.HEIGHT) | |||
| self.arg = math.radians (random.randrange (360)) | |||
| if (not self.balloon.enabled) and self.talking: | |||
| self.talking = False | |||
| if (self.balloon.enabled and self.balloon.frame >= FPS * 3 | |||
| and not self.talking): | |||
| self.read_out () | |||
| def talk ( | |||
| self, | |||
| query: str, | |||
| answer: str, | |||
| ) -> None: | |||
| self.bell () | |||
| self._create_wav (answer) | |||
| length = 300 | |||
| if self.wav is not None: | |||
| with wave.open ('./nizika_talking.wav', 'rb') as f: | |||
| length = int (FPS * (f.getnframes () / f.getframerate () + 4)) | |||
| self.balloon.talk (query, answer, length = length) | |||
| def read_out ( | |||
| self, | |||
| ) -> None: | |||
| Sound ('./nizika_talking.wav').play () | |||
| self.talking = True | |||
| def _create_wav ( | |||
| self, | |||
| message: str, | |||
| ) -> None: | |||
| try: | |||
| self.wav = Aques.main (message, False) | |||
| except: | |||
| self.wav = None | |||
| if self.wav is None: | |||
| return | |||
| with open ('./nizika_talking.wav', 'wb') as f: | |||
| f.write (self.wav) | |||
| class CurrentTime (GameObject): | |||