feat: Wordle interaction
This commit is contained in:
parent
7167b4c34c
commit
171f760d4e
@ -22,4 +22,4 @@ Frontend je napsaný ve Vanilla Javě. Config soubor se automaticky ukládá v n
|
|||||||
|
|
||||||
- Unix-like operační systémy: `~/.config/Chronos/config.json`
|
- Unix-like operační systémy: `~/.config/Chronos/config.json`
|
||||||
- Windows: `C:\Users\<username>\AppData\Chronos\config.json`
|
- Windows: `C:\Users\<username>\AppData\Chronos\config.json`
|
||||||
- MaxOS: `~/Library/Application Support/Chronos/config.json`
|
- MacOS: `~/Library/Application Support/Chronos/config.json`
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package cz.jzitnik.chronos.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class AppConfig {
|
||||||
|
@Bean
|
||||||
|
public RestTemplate restTemplate() {
|
||||||
|
return new RestTemplate();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package cz.jzitnik.chronos.controllers;
|
package cz.jzitnik.chronos.controllers;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import cz.jzitnik.chronos.entities.Item;
|
import cz.jzitnik.chronos.entities.Item;
|
||||||
import cz.jzitnik.chronos.entities.Message;
|
import cz.jzitnik.chronos.entities.Message;
|
||||||
import cz.jzitnik.chronos.entities.MessageType;
|
import cz.jzitnik.chronos.entities.MessageType;
|
||||||
|
@ -25,6 +25,7 @@ public class Interaction {
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private Character character;
|
private Character character;
|
||||||
|
|
||||||
|
@Lob
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private String memory;
|
private String memory;
|
||||||
|
|
||||||
|
@ -2,5 +2,6 @@ package cz.jzitnik.chronos.interactions;
|
|||||||
|
|
||||||
public enum Interaction {
|
public enum Interaction {
|
||||||
Farmer,
|
Farmer,
|
||||||
Cashier
|
Cashier,
|
||||||
|
Librarian
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import cz.jzitnik.chronos.entities.Player;
|
|||||||
import cz.jzitnik.chronos.entities.Character;
|
import cz.jzitnik.chronos.entities.Character;
|
||||||
import cz.jzitnik.chronos.interactions.list.Hangman;
|
import cz.jzitnik.chronos.interactions.list.Hangman;
|
||||||
import cz.jzitnik.chronos.interactions.list.RockPaperScissors;
|
import cz.jzitnik.chronos.interactions.list.RockPaperScissors;
|
||||||
|
import cz.jzitnik.chronos.interactions.list.wordle.Wordle;
|
||||||
import cz.jzitnik.chronos.payload.responses.InteractionResponse;
|
import cz.jzitnik.chronos.payload.responses.InteractionResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -12,9 +13,10 @@ import org.springframework.stereotype.Service;
|
|||||||
public class InteractionService {
|
public class InteractionService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private RockPaperScissors rockPaperScissors;
|
private RockPaperScissors rockPaperScissors;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Hangman hangman;
|
private Hangman hangman;
|
||||||
|
@Autowired
|
||||||
|
private Wordle wordle;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Function3<T, U, V, W> {
|
public interface Function3<T, U, V, W> {
|
||||||
@ -25,6 +27,7 @@ public class InteractionService {
|
|||||||
return switch (interaction) {
|
return switch (interaction) {
|
||||||
case Farmer -> rockPaperScissors::play;
|
case Farmer -> rockPaperScissors::play;
|
||||||
case Cashier -> hangman::play;
|
case Cashier -> hangman::play;
|
||||||
|
case Librarian -> wordle::play;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -59,7 +59,6 @@ public class Hangman implements InteractionPlayer {
|
|||||||
try {
|
try {
|
||||||
return objectMapper.readValue(memory, HangmanMemory.class);
|
return objectMapper.readValue(memory, HangmanMemory.class);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(e);
|
|
||||||
throw new RuntimeException("Somebody just fucked up db."); // If this happens idk what is wrong with my life
|
throw new RuntimeException("Somebody just fucked up db."); // If this happens idk what is wrong with my life
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,234 @@
|
|||||||
|
package cz.jzitnik.chronos.interactions.list.wordle;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import cz.jzitnik.chronos.entities.Item;
|
||||||
|
import cz.jzitnik.chronos.entities.ItemType;
|
||||||
|
import cz.jzitnik.chronos.entities.Player;
|
||||||
|
import cz.jzitnik.chronos.entities.Character;
|
||||||
|
import cz.jzitnik.chronos.interactions.InteractionPlayer;
|
||||||
|
import cz.jzitnik.chronos.payload.responses.InteractionResponse;
|
||||||
|
import cz.jzitnik.chronos.repository.CharacterRepository;
|
||||||
|
import cz.jzitnik.chronos.services.ItemService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class Wordle implements InteractionPlayer {
|
||||||
|
@Autowired
|
||||||
|
private CharacterRepository characterRepository;
|
||||||
|
@Autowired
|
||||||
|
private ItemService itemService;
|
||||||
|
@Autowired
|
||||||
|
private WordleService wordleService;
|
||||||
|
|
||||||
|
private static final int ATTEMPTS = 6; // Max attempts for Wordle
|
||||||
|
|
||||||
|
public enum FeedbackType {
|
||||||
|
NOT_IN_WORD,
|
||||||
|
WRONG_POSITION,
|
||||||
|
CORRECT_POSITION
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public static class CharacterFeedback {
|
||||||
|
private char character;
|
||||||
|
private FeedbackType feedbackType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public static class GuessFeedback {
|
||||||
|
private String guess;
|
||||||
|
private List<CharacterFeedback> feedback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private static class WordleMemory {
|
||||||
|
private String word;
|
||||||
|
private List<GuessFeedback> feedbackHistory;
|
||||||
|
private int attemptsRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WordleMemory readMemory(String memory) {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
return objectMapper.readValue(memory, WordleMemory.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
throw new RuntimeException("Error reading memory from DB.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String writeMemory(WordleMemory memory) {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
try {
|
||||||
|
return objectMapper.writeValueAsString(memory);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private static class WordleResponse {
|
||||||
|
public enum Type {
|
||||||
|
GAME_CREATED,
|
||||||
|
GAME_WON,
|
||||||
|
GAME_LOST,
|
||||||
|
GAME_CONTINUE,
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type type;
|
||||||
|
private List<GuessFeedback> feedbackHistory;
|
||||||
|
private int attemptsRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResponse play(Player player, Character character, String data) {
|
||||||
|
if (character.getInteractionData().getPlayer() == null) {
|
||||||
|
// New game
|
||||||
|
try {
|
||||||
|
return initGame(player, character);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game already exists
|
||||||
|
if (!character.getInteractionData().getPlayer().getId().equals(player.getId())) {
|
||||||
|
return new InteractionResponse(false, "already_playing", new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return makeGuess(player, character, data);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InteractionResponse initGame(Player player, Character character) throws JsonProcessingException {
|
||||||
|
var interactionData = character.getInteractionData();
|
||||||
|
interactionData.setPlayer(player);
|
||||||
|
|
||||||
|
interactionData.setMemory(writeMemory(new WordleMemory(wordleService.fetchWordleSolution(), new ArrayList<>(), ATTEMPTS)));
|
||||||
|
|
||||||
|
characterRepository.save(character);
|
||||||
|
|
||||||
|
var response = new WordleResponse(WordleResponse.Type.GAME_CREATED, new ArrayList<>(), ATTEMPTS);
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
return new InteractionResponse(true, objectMapper.writeValueAsString(response), new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private InteractionResponse makeGuess(Player player, Character character, String data) throws JsonProcessingException {
|
||||||
|
var interactionMemory = readMemory(character.getInteractionData().getMemory());
|
||||||
|
|
||||||
|
if (data.equals("get_data")) {
|
||||||
|
var response = new WordleResponse(WordleResponse.Type.GAME_CONTINUE, interactionMemory.getFeedbackHistory(), interactionMemory.getAttemptsRemaining());
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
return new InteractionResponse(false, objectMapper.writeValueAsString(response), new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
String word = interactionMemory.getWord();
|
||||||
|
List<GuessFeedback> feedbackHistory = interactionMemory.getFeedbackHistory();
|
||||||
|
|
||||||
|
if (data.length() != 5) {
|
||||||
|
return new InteractionResponse(false, "invalid_input", new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feedbackHistory.stream().anyMatch(f -> f.getGuess().equals(data))) {
|
||||||
|
return new InteractionResponse(false, "already_guessed", new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CharacterFeedback> feedback = generateFeedback(word, data);
|
||||||
|
feedbackHistory.add(new GuessFeedback(data, feedback));
|
||||||
|
interactionMemory.setFeedbackHistory(feedbackHistory);
|
||||||
|
|
||||||
|
interactionMemory.setAttemptsRemaining(interactionMemory.getAttemptsRemaining() - 1);
|
||||||
|
|
||||||
|
if (data.equals(word)) {
|
||||||
|
var item = new Item(ItemType.KEY_FRAGMENT, player);
|
||||||
|
itemService.addItem(player, item);
|
||||||
|
|
||||||
|
character.setInteractedWith(true);
|
||||||
|
characterRepository.save(character);
|
||||||
|
|
||||||
|
var items = new ArrayList<Item>();
|
||||||
|
items.add(item);
|
||||||
|
|
||||||
|
var response = new WordleResponse(WordleResponse.Type.GAME_WON, feedbackHistory, interactionMemory.getAttemptsRemaining());
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
return new InteractionResponse(true, objectMapper.writeValueAsString(response), items);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactionMemory.getAttemptsRemaining() == 0) {
|
||||||
|
character.setInteractedWith(true);
|
||||||
|
characterRepository.save(character);
|
||||||
|
|
||||||
|
var response = new WordleResponse(WordleResponse.Type.GAME_LOST, feedbackHistory, interactionMemory.getAttemptsRemaining());
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
return new InteractionResponse(false, objectMapper.writeValueAsString(response), new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
character.getInteractionData().setMemory(writeMemory(interactionMemory));
|
||||||
|
characterRepository.save(character);
|
||||||
|
|
||||||
|
var response = new WordleResponse(WordleResponse.Type.GAME_CONTINUE, feedbackHistory, interactionMemory.getAttemptsRemaining());
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
return new InteractionResponse(false, objectMapper.writeValueAsString(response), new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CharacterFeedback> generateFeedback(String word, String guess) {
|
||||||
|
List<CharacterFeedback> feedback = new ArrayList<>();
|
||||||
|
boolean[] matched = new boolean[word.length()];
|
||||||
|
|
||||||
|
// First pass: Check for correct positions
|
||||||
|
for (int i = 0; i < word.length(); i++) {
|
||||||
|
if (guess.charAt(i) == word.charAt(i)) {
|
||||||
|
feedback.add(new CharacterFeedback(guess.charAt(i), FeedbackType.CORRECT_POSITION));
|
||||||
|
matched[i] = true;
|
||||||
|
} else {
|
||||||
|
feedback.add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second pass: Check for incorrect positions
|
||||||
|
for (int i = 0; i < word.length(); i++) {
|
||||||
|
if (feedback.get(i) != null) continue;
|
||||||
|
|
||||||
|
char guessChar = guess.charAt(i);
|
||||||
|
boolean found = false;
|
||||||
|
for (int j = 0; j < word.length(); j++) {
|
||||||
|
if (!matched[j] && word.charAt(j) == guessChar) {
|
||||||
|
feedback.set(i, new CharacterFeedback(guessChar, FeedbackType.WRONG_POSITION));
|
||||||
|
matched[j] = true;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
feedback.set(i, new CharacterFeedback(guessChar, FeedbackType.NOT_IN_WORD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return feedback;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package cz.jzitnik.chronos.interactions.list.wordle;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WordleResponse {
|
||||||
|
private String solution;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package cz.jzitnik.chronos.interactions.list.wordle;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class WordleService {
|
||||||
|
@Autowired
|
||||||
|
private RestTemplate restTemplate;
|
||||||
|
|
||||||
|
public String fetchWordleSolution() {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
String formattedDate = today.toString(); // Format: YYYY-MM-DD
|
||||||
|
|
||||||
|
String url = "https://www.nytimes.com/svc/wordle/v2/" + formattedDate + ".json";
|
||||||
|
|
||||||
|
WordleResponse response = restTemplate.getForObject(url, WordleResponse.class);
|
||||||
|
|
||||||
|
return response != null ? response.getSolution() : "ahead"; // Idk another word than ahead
|
||||||
|
}
|
||||||
|
}
|
@ -69,9 +69,31 @@ public class InitGameService {
|
|||||||
shop_characters.add(cashier);
|
shop_characters.add(cashier);
|
||||||
shop.setCharacters(shop_characters);
|
shop.setCharacters(shop_characters);
|
||||||
|
|
||||||
|
// Knihovna
|
||||||
|
var library = new Room(
|
||||||
|
"Knihovna",
|
||||||
|
game
|
||||||
|
);
|
||||||
|
var library_characters = new ArrayList<Character>();
|
||||||
|
var librarian = new Character(
|
||||||
|
"Knihovník",
|
||||||
|
library,
|
||||||
|
"Ahoj já jsem knihovník a budeš se mnou hrát wordle."
|
||||||
|
);
|
||||||
|
librarian.setInteraction(Interaction.Librarian);
|
||||||
|
librarian.setInteractionData(new cz.jzitnik.chronos.entities.Interaction(
|
||||||
|
"Tak si zahrajeme wordle.",
|
||||||
|
"Se mnou někdo již hrál wordle. Další fragment klíče nemám.",
|
||||||
|
librarian
|
||||||
|
));
|
||||||
|
library_characters.add(librarian);
|
||||||
|
library.setCharacters(library_characters);
|
||||||
|
|
||||||
|
|
||||||
rooms.add(outside);
|
rooms.add(outside);
|
||||||
rooms.add(stodola);
|
rooms.add(stodola);
|
||||||
rooms.add(shop);
|
rooms.add(shop);
|
||||||
|
rooms.add(library);
|
||||||
|
|
||||||
game.setRooms(rooms);
|
game.setRooms(rooms);
|
||||||
|
|
||||||
|
@ -2,5 +2,6 @@ package cz.jzitnik.api.types;
|
|||||||
|
|
||||||
public enum Interaction {
|
public enum Interaction {
|
||||||
Farmer,
|
Farmer,
|
||||||
Cashier
|
Cashier,
|
||||||
|
Librarian
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cz.jzitnik.game.interactions;
|
package cz.jzitnik.game.interactions;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import cz.jzitnik.api.ApiService;
|
import cz.jzitnik.api.ApiService;
|
||||||
import cz.jzitnik.api.requests.InteractionRequest;
|
import cz.jzitnik.api.requests.InteractionRequest;
|
||||||
|
@ -20,7 +20,6 @@ public class Interactions {
|
|||||||
|
|
||||||
Cli.type(character, interactionData.getStartText());
|
Cli.type(character, interactionData.getStartText());
|
||||||
|
|
||||||
// "Object _ =" is just for java compiler to ensure that all interactions are covered.
|
|
||||||
switch (character.getInteraction()) {
|
switch (character.getInteraction()) {
|
||||||
case Farmer -> {
|
case Farmer -> {
|
||||||
var options = new String[]{"Kámen", "Nůžky", "Papír"};
|
var options = new String[]{"Kámen", "Nůžky", "Papír"};
|
||||||
@ -42,6 +41,10 @@ public class Interactions {
|
|||||||
Hangman hangman = new Hangman(character, apiService, playerKey);
|
Hangman hangman = new Hangman(character, apiService, playerKey);
|
||||||
hangman.play();
|
hangman.play();
|
||||||
}
|
}
|
||||||
|
case Librarian -> {
|
||||||
|
Wordle wordle = new Wordle(character, apiService, playerKey);
|
||||||
|
wordle.play();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
136
frontend/src/main/java/cz/jzitnik/game/interactions/Wordle.java
Normal file
136
frontend/src/main/java/cz/jzitnik/game/interactions/Wordle.java
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
package cz.jzitnik.game.interactions;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import cz.jzitnik.api.ApiService;
|
||||||
|
import cz.jzitnik.api.requests.InteractionRequest;
|
||||||
|
import cz.jzitnik.api.responses.InteractionResponse;
|
||||||
|
import cz.jzitnik.api.types.Character;
|
||||||
|
import cz.jzitnik.utils.Cli;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.Console;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Wordle {
|
||||||
|
private Character character;
|
||||||
|
private ApiService apiService;
|
||||||
|
private String playerKey;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static class WordleResponse {
|
||||||
|
public enum Type {
|
||||||
|
GAME_CREATED,
|
||||||
|
GAME_WON,
|
||||||
|
GAME_LOST,
|
||||||
|
GAME_CONTINUE,
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type type;
|
||||||
|
private int attemptsRemaining;
|
||||||
|
private List<GuessFeedback> feedbackHistory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static class GuessFeedback {
|
||||||
|
private String guess;
|
||||||
|
private List<CharacterFeedback> feedback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static class CharacterFeedback {
|
||||||
|
private char character;
|
||||||
|
private FeedbackType feedbackType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FeedbackType {
|
||||||
|
NOT_IN_WORD,
|
||||||
|
WRONG_POSITION,
|
||||||
|
CORRECT_POSITION
|
||||||
|
}
|
||||||
|
|
||||||
|
public void play() throws IOException {
|
||||||
|
var response = apiService.isInteracting(playerKey, character.getId()).execute();
|
||||||
|
var interacting = response.body().getData().get();
|
||||||
|
|
||||||
|
if (!interacting) {
|
||||||
|
init();
|
||||||
|
} else {
|
||||||
|
// Get data where we left off
|
||||||
|
var body = apiService.interact(playerKey, new InteractionRequest("get_data", character.getId())).execute().body();
|
||||||
|
var data = body.getData().get();
|
||||||
|
gameContinue(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() throws IOException {
|
||||||
|
var body = apiService.interact(playerKey, new InteractionRequest("", character.getId())).execute().body();
|
||||||
|
var data = body.getData().get();
|
||||||
|
gameContinue(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gameContinue(InteractionResponse data) throws IOException {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
var wordleData = objectMapper.readValue(data.getResponseText(), WordleResponse.class);
|
||||||
|
|
||||||
|
switch (wordleData.getType()) {
|
||||||
|
case GAME_WON -> {
|
||||||
|
Cli.type(character, "Vyhrál jsi! Slovo bylo: " + getCurrentWord(wordleData.getFeedbackHistory()));
|
||||||
|
Cli.gotItems(data.getItems());
|
||||||
|
}
|
||||||
|
case GAME_LOST -> Cli.type(character, "Prohrál jsi! Bohužel jste neuhodl slovo. Fragment klíče nedostanete.");
|
||||||
|
case GAME_CONTINUE, GAME_CREATED -> {
|
||||||
|
System.out.println("Zbývající pokusy: " + wordleData.getAttemptsRemaining());
|
||||||
|
displayFeedback(wordleData.getFeedbackHistory());
|
||||||
|
|
||||||
|
var guess = askForWord();
|
||||||
|
var response = apiService.interact(playerKey, new InteractionRequest(guess, character.getId())).execute();
|
||||||
|
var body = response.body().getData().get();
|
||||||
|
|
||||||
|
gameContinue(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String askForWord() {
|
||||||
|
Console console = System.console();
|
||||||
|
|
||||||
|
String word = console.readLine("Zadejte slovo (5 písmen): ");
|
||||||
|
|
||||||
|
if (word.length() != 5) {
|
||||||
|
Cli.error("Neplatný vstup! Slovo musí mít 5 písmen.");
|
||||||
|
return askForWord();
|
||||||
|
}
|
||||||
|
|
||||||
|
return word.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayFeedback(List<GuessFeedback> feedbackHistory) {
|
||||||
|
for (var feedback : feedbackHistory) {
|
||||||
|
System.out.print(feedback.getGuess() + " -> ");
|
||||||
|
|
||||||
|
for (var charFeedback : feedback.getFeedback()) {
|
||||||
|
String color = switch (charFeedback.getFeedbackType()) {
|
||||||
|
case CORRECT_POSITION -> Cli.Colors.GREEN;
|
||||||
|
case WRONG_POSITION -> Cli.Colors.YELLOW;
|
||||||
|
case NOT_IN_WORD -> "";
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.print(color + charFeedback.getCharacter() + Cli.Colors.RESET);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCurrentWord(List<GuessFeedback> feedbackHistory) {
|
||||||
|
for (var feedback : feedbackHistory) {
|
||||||
|
if (feedback.getFeedback().stream().allMatch(f -> f.getFeedbackType() == FeedbackType.CORRECT_POSITION)) {
|
||||||
|
return feedback.getGuess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user