2025-04-12 11:58:01 +02:00
|
|
|
import logging
|
2025-04-12 12:59:36 +02:00
|
|
|
import threading
|
|
|
|
import time
|
2025-04-12 11:58:01 +02:00
|
|
|
from typing import Literal, Dict, Any
|
|
|
|
import config
|
|
|
|
from dto.requests import GameStartRequestDTO, GameDecisionRequestDTO
|
2025-04-12 21:47:57 +02:00
|
|
|
from services.extractor import extract_profile, extract_passport, extract_description, extract_account
|
2025-04-12 11:58:01 +02:00
|
|
|
from services.julius_baer_api_client import JuliusBaerApiClient
|
2025-04-12 21:47:57 +02:00
|
|
|
from utils.storage.game_files_manager import store_game_round_data
|
|
|
|
|
2025-04-12 11:58:01 +02:00
|
|
|
|
2025-04-12 13:59:59 +02:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
2025-04-12 11:58:01 +02:00
|
|
|
|
|
|
|
class Player:
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.client = JuliusBaerApiClient()
|
2025-04-12 12:59:36 +02:00
|
|
|
self._thread = None
|
2025-04-12 11:58:01 +02:00
|
|
|
|
|
|
|
def start(self):
|
|
|
|
self.play()
|
|
|
|
|
2025-04-12 12:59:36 +02:00
|
|
|
def play_on_separate_thread(self):
|
|
|
|
if self._thread and self._thread.is_alive():
|
2025-04-12 13:59:59 +02:00
|
|
|
log.warning('Game loop already running.')
|
2025-04-12 12:59:36 +02:00
|
|
|
return self._thread
|
|
|
|
|
|
|
|
self._thread = threading.Thread(target=self.play, daemon=True)
|
|
|
|
self._thread.start()
|
|
|
|
return self._thread
|
|
|
|
|
2025-04-12 11:58:01 +02:00
|
|
|
def play(self):
|
2025-04-12 13:59:59 +02:00
|
|
|
log.info('playing')
|
2025-04-12 11:58:01 +02:00
|
|
|
payload = GameStartRequestDTO(player_name=config.API_TEAM)
|
|
|
|
start_response = self.client.start_game(payload)
|
2025-04-12 13:59:59 +02:00
|
|
|
log.info('game started, session id: %s', start_response.session_id)
|
2025-04-12 11:58:01 +02:00
|
|
|
|
2025-04-12 21:47:57 +02:00
|
|
|
client_id = start_response.client_id
|
2025-04-12 11:58:01 +02:00
|
|
|
decision = self.make_decision(start_response.client_data)
|
|
|
|
|
2025-04-12 13:40:51 +02:00
|
|
|
decision_counter = 0
|
|
|
|
|
2025-04-12 15:41:45 +02:00
|
|
|
is_game_running = True
|
|
|
|
while is_game_running:
|
2025-04-12 11:58:01 +02:00
|
|
|
payload = GameDecisionRequestDTO(
|
|
|
|
decision=decision,
|
|
|
|
session_id=start_response.session_id,
|
2025-04-12 15:41:45 +02:00
|
|
|
client_id=client_id,
|
2025-04-12 11:58:01 +02:00
|
|
|
)
|
|
|
|
|
2025-04-12 15:41:45 +02:00
|
|
|
log.info('client id: %s', client_id)
|
2025-04-12 12:51:13 +02:00
|
|
|
decision_response = self.client.send_decision(payload)
|
2025-04-12 13:59:59 +02:00
|
|
|
log.info(f'decision: {decision}, response status: {decision_response.status}, score: {decision_response.score}')
|
2025-04-12 15:41:45 +02:00
|
|
|
|
2025-04-12 11:58:01 +02:00
|
|
|
status = decision_response.status
|
2025-04-12 15:41:45 +02:00
|
|
|
is_game_running = status not in ['gameover', 'complete']
|
|
|
|
client_id = decision_response.client_id
|
|
|
|
|
2025-04-12 11:58:01 +02:00
|
|
|
decision = self.make_decision(decision_response.client_data)
|
2025-04-12 13:40:51 +02:00
|
|
|
|
2025-04-12 14:00:11 +02:00
|
|
|
# Handle first response from game initialization logic
|
|
|
|
if decision_counter == 0:
|
|
|
|
# Store start response
|
|
|
|
store_game_round_data(decision, start_response, decision_counter, str(start_response.session_id) ,status)
|
|
|
|
else:
|
|
|
|
# store ongoing decision response
|
|
|
|
store_game_round_data(decision, decision_response, decision_counter, str(start_response.session_id), status)
|
2025-04-12 13:40:51 +02:00
|
|
|
|
|
|
|
decision_counter += 1
|
2025-04-12 15:41:45 +02:00
|
|
|
time.sleep(1)
|
2025-04-12 14:00:11 +02:00
|
|
|
|
2025-04-12 11:58:01 +02:00
|
|
|
def make_decision(self, client_data: Dict[str, Any]) -> Literal["Accept", "Reject"]:
|
2025-04-12 21:47:57 +02:00
|
|
|
# Data extraction
|
|
|
|
profile = extract_profile(client_data)
|
|
|
|
passport = extract_passport(client_data)
|
|
|
|
description = extract_description(client_data)
|
|
|
|
account = extract_account(client_data)
|
|
|
|
|
|
|
|
prompt_template = (
|
|
|
|
"You are a helpful assistant at a private bank.\n"
|
|
|
|
"Your task is to accept or reject a new client's application for private banking.\n\n"
|
|
|
|
"Only reject the application if there is an inconsistency in the data provided.\n"
|
|
|
|
"Inconsistencies include:\n"
|
|
|
|
"- Incorrect data (e.g., mismatched or invalid information)\n"
|
|
|
|
"- Incomplete data (e.g., missing required fields)\n\n"
|
|
|
|
"Return only JSON matching this format:\n"
|
|
|
|
"{format_instructions}\n\n"
|
|
|
|
"Here is the extracted passport text:\n"
|
|
|
|
"{processed_text}\n\n"
|
|
|
|
"Use the extracted profile, description, and account details to check consistency."
|
|
|
|
)
|
|
|
|
|
|
|
|
# You'd insert the format instructions and passport text here before calling the LLM
|
|
|
|
# For example:
|
|
|
|
# final_prompt = prompt_template.format(
|
|
|
|
# format_instructions=your_format_instructions,
|
|
|
|
# processed_text=passport['text']
|
|
|
|
# )
|
2025-04-12 11:58:01 +02:00
|
|
|
|
2025-04-12 15:41:45 +02:00
|
|
|
return 'Accept' # Replace me!!
|