mmmewk / crosswordle

MIT License
6 stars 3 forks source link

Unicode Puzzle Character Issues #11

Closed muhelen closed 2 years ago

muhelen commented 2 years ago

Hi, while forking to build on my Tamil language, I stumbled upon some unicode character problem on Crossword.tsx file with guessedLetter.

Screenshot 2022-03-02 at பிற்பகல் 9 16 06

If you could see on the screenshot, I've implemented grapheme splitter to the grid letters and it works, but unable to do it on the puzzle box. Could you point me the right way to fix this? Thanks.

mmmewk commented 2 years ago

Hmm, I can take a look tonight but not sure if I would know any better than you why its not working. Can you make sure your forked project is up to date on github so I can clone it locally and play around?

mmmewk commented 2 years ago

I also wonder if we can make the separate language builds part of this one. Maybe a language selector at the top and then each language has its own set of puzzles? That way as new features are added to the original build they get applied to all languages.

If we go down that route it would be cool to have a dictionary feature when you can click on a word and it tells you what it means, that way language learners can use this game to expand their vocabulary.

muhelen commented 2 years ago

Hmm, I can take a look tonight but not sure if I would know any better than you why its not working. Can you make sure your forked project is up to date on github so I can clone it locally and play around?

Hi, Thanks for the reply. I've updated my fork with some easy Tamil keyboard layout for your testing.

Screenshot 2022-03-03 at முற்பகல் 1 03 47

First row = dependants , Second row = vowels, Third & forth row = consonants Vowels are independent characters, while consonants + dependants will form compound (combine) consonants.

It's basically last two rows + first row characters will form 1 joined letter. Let me know if you need further help on this layout understanding.

muhelen commented 2 years ago

I also wonder if we can make the separate language builds part of this one. Maybe a language selector at the top and then each language has its own set of puzzles? That way as new features are added to the original build they get applied to all languages.

If we go down that route it would be cool to have a dictionary feature when you can click on a word and it tells you what it means, that way language learners can use this game to expand their vocabulary.

This is good suggestions, but it may require further extra development on different language complexity. For Tamil, it's total of 247 letters altogether. I'm keen on this development, but not sure about other languages. Let's explore it and sure it will be a good learning experiences and will benefit more larger communities.

mmmewk commented 2 years ago

@muhelen Ok I think I understand the issue:

1) You need to update the getGuessedLetter function to use your unicode splitter on the return statement. This is the function that sets the blue text. 2) you need to update the guessWord function where it says Array.from(guess) you want to use your unicode splitter. That is the function that saves whatever letters you got correct to the crossword grid.

mmmewk commented 2 years ago

2 other issues I see: 1) The font size of the the letters maybe needs to get smaller if they are really long to fit in the squares 2) My function moveToNextGuessSquare was implemented pretty lazily assuming that each keystroke would be a single character. It actually works off the fact that the state of currentGuess hasn't yet updated. I'll fix that in my code too.

This should work instead for you, instead of moving relative to your current position when you type move to the square that is unicodeLength(newGuess) away from the start:

  // After keyboard input move to the next square where you can type
  const moveToLetterIndex = useCallback((index: number) => {
    let { row, col } = focusedWordData;
    if (focusedDirection === 'across') col += index;
    if (focusedDirection === 'down') row += index;
    crosswordRef.current?.moveTo(row, col);
  }, [focusedDirection, crosswordRef, focusedWordData]);

  // Key event callbacks
  const onChar = (value: string) => {
    const guessesForWord = guesses[focusedDirection][focusedNumber];

    if (unicodeLength(currentGuess) < currentWord.length && guessesForWord.length < 6) {
      const newGuess = `${currentGuess}${value}`;
      setCurrentGuess(newGuess);
      moveToLetterIndex(unicodeLength(newGuess));
    }
  }

  const onDelete = () => {
    const newGuess = currentGuess.slice(0, -1);
    setCurrentGuess(newGuess);
    moveToLetterIndex(unicodeLength(newGuess));
  }
mmmewk commented 2 years ago

Hope that helps! Stoked to see your version live!

muhelen commented 2 years ago

2 other issues I see:

  1. The font size of the the letters maybe needs to get smaller if they are really long to fit in the squares
  2. My function moveToNextGuessSquare was implemented pretty lazily assuming that each keystroke would be a single character. It actually works off the fact that the state of currentGuess hasn't yet updated. I'll fix that in my code too.

This should work instead for you, instead of moving relative to your current position when you type move to the square that is unicodeLength(newGuess) away from the start:

  // After keyboard input move to the next square where you can type
  const moveToLetterIndex = useCallback((index: number) => {
    let { row, col } = focusedWordData;
    if (focusedDirection === 'across') col += index;
    if (focusedDirection === 'down') row += index;
    crosswordRef.current?.moveTo(row, col);
  }, [focusedDirection, crosswordRef, focusedWordData]);

  // Key event callbacks
  const onChar = (value: string) => {
    const guessesForWord = guesses[focusedDirection][focusedNumber];

    if (unicodeLength(currentGuess) < currentWord.length && guessesForWord.length < 6) {
      const newGuess = `${currentGuess}${value}`;
      setCurrentGuess(newGuess);
      moveToLetterIndex(unicodeLength(newGuess));
    }
  }

  const onDelete = () => {
    const newGuess = currentGuess.slice(0, -1);
    setCurrentGuess(newGuess);
    moveToLetterIndex(unicodeLength(newGuess));
  }

Hi @mmmewk Yes, this works for the guesses. 👍🏼

@muhelen Ok I think I understand the issue:

  1. You need to update the getGuessedLetter function to use your unicode splitter on the return statement. This is the function that sets the blue text.
  2. you need to update the guessWord function where it says Array.from(guess) you want to use your unicode splitter. That is the function that saves whatever letters you got correct to the crossword grid.

But, I'm still struggling with this code. Could you provide me some example. The puzzle grid still couldn't ...

mmmewk commented 2 years ago

Yeah for getGuessedLetter:

const getGuessedLetter = (cell: CellData) => {
    if (!cell.used || !guess) return;

    const focusedNumber = focusedCell[focusedDirection];

    if (!focusedNumber || cell[focusedDirection] !== focusedNumber) return;
    const focusedWord = crossword[focusedDirection][focusedNumber];
    const letterIndex = cell.row - focusedWord.row || cell.col - focusedWord.col;
    return unicodeSplit(guess)[letterIndex];
  };

and for guessWord:

guessWord: (guess: string) => {
      const focusedNumber = focusedCell[focusedDirection];

      if (!focusedNumber) return;
      const focusedWord = crossword[focusedDirection][focusedNumber];

      const gridDataClone = cloneDeep(gridData);

      let { row, col, answer } = focusedWord;
      unicodeSplit(guess).forEach((letter, index) => {
        const newRow = row + (focusedDirection === 'down' ? index : 0);
        const newCol = col + (focusedDirection === 'across' ? index : 0);
        const cellClone = gridDataClone[newRow][newCol];
        if (!cellClone.used) return;
        if (letter === answer[index]) cellClone.guess = letter;
      });

      setGridData(gridDataClone);
    },
mmmewk commented 2 years ago

Let me know if that works as expected!

muhelen commented 2 years ago

Yeah for getGuessedLetter:

const getGuessedLetter = (cell: CellData) => {
    if (!cell.used || !guess) return;

    const focusedNumber = focusedCell[focusedDirection];

    if (!focusedNumber || cell[focusedDirection] !== focusedNumber) return;
    const focusedWord = crossword[focusedDirection][focusedNumber];
    const letterIndex = cell.row - focusedWord.row || cell.col - focusedWord.col;
    return unicodeSplit(guess)[letterIndex];
  };

and for guessWord:

guessWord: (guess: string) => {
      const focusedNumber = focusedCell[focusedDirection];

      if (!focusedNumber) return;
      const focusedWord = crossword[focusedDirection][focusedNumber];

      const gridDataClone = cloneDeep(gridData);

      let { row, col, answer } = focusedWord;
      unicodeSplit(guess).forEach((letter, index) => {
        const newRow = row + (focusedDirection === 'down' ? index : 0);
        const newCol = col + (focusedDirection === 'across' ? index : 0);
        const cellClone = gridDataClone[newRow][newCol];
        if (!cellClone.used) return;
        if (letter === answer[index]) cellClone.guess = letter;
      });

      setGridData(gridDataClone);
    },

@mmmewk Yes, its now combining the characters correctly. But the last letters not working properly. It's jumping to next word when doing the combination... It's look like moveToNextGuessSquare taking place before the word finishes...

mmmewk commented 2 years ago

Ahh yeah are there certain queues you can use to know when the letter is completed? You can just remove the whole moveToNextGuessSquare logic, it was just a convenience thing. Or if you know that a letter is complete only then do you move to the next square

muhelen commented 2 years ago

@mmmewk moveToNextGuessSquare is a good feature. Let me play around with the words to see how it's working with different combinations.

I've noticed you've updated some nice features to the main repo. It's looks awesome. Will try to sync with your changes. Thanks again.

mmmewk commented 2 years ago

Yup just added a bit more, sorry it won't merge nicely with your unicode splitter, might require further development. I could probably implement the unicode splitter on my end to make it easier for anyone developing with different languages to fork my repo

muhelen commented 2 years ago

@mmmewk That's great news 😊👌👌 Meanwhile I'll try to use my modified version unicode splitter.. Thanks.

muhelen commented 2 years ago

@mmmewk I've rectified most of the unicode errors. I'm having an issue as below :

When enter the correct word on the guesses, it doesn't return anything. If I enter additional letter, the screen goes blank. If enter wrong word, it return word not found message.

You can check my fork repo. Could you highlight me what's not woking here. Thanks.

mmmewk commented 2 years ago

Hey, sorry was out of town this last weekend. I can take a look today or tomorrow after work, for the word not found message you need to update public/validWords.json to include words in your language, right now it only includes english words of 3-5 letters

mmmewk commented 2 years ago

For the correct word I'm not sure, try seeing if there are any console errors?

muhelen commented 2 years ago

@mmmewk Hi, yes I already updated the validwords.json with Tamil words with many combinations. Hope you can find out why the errors occurs. Thanks.

mmmewk commented 2 years ago

Created a PR into your branch, just more locations where you need to use unicodeLength rather than .length

mmmewk commented 2 years ago

Closing this issue as its related to your fork rather than mine, Happy to help in the future though looks like your branch is pretty close to working!

muhelen commented 2 years ago

Created a PR into your branch, just more locations where you need to use unicodeLength rather than .length

Hi, I can't view the PR. Could you resend again? Thanks.

mmmewk commented 2 years ago

Oops sorry, just reopened it