8000 Feature: Play multiple mulitplayer games based on one invitation by hhpmmd · Pull Request #331 · lexica/lexica · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Feature: Play multiple mulitplayer games based on one invitation #331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/main/java/com/serwylo/lexica/GameActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.serwylo.lexica.db.Database;
import com.serwylo.lexica.db.GameMode;
import com.serwylo.lexica.db.ResultRepository;
import com.serwylo.lexica.game.CharProbGenerator;
import com.serwylo.lexica.game.Game;
import com.serwylo.lexica.lang.Language;
import com.serwylo.lexica.view.LexicaView;
Expand Down Expand Up @@ -100,7 +101,7 @@ public void onCreate(Bundle savedInstanceState) {
Language language = Language.from(langName);

game = board != null
? new Game(this, gameMode, language, board)
? new Game(this, gameMode, language, new CharProbGenerator.BoardSeed(board))
: Game.generateGame(this, gameMode, language);

setupGameView(game);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ import com.serwylo.lexica.db.GameModeRepository
import com.serwylo.lexica.game.Game
import com.serwylo.lexica.share.SharedGameData
import com.serwylo.lexica.share.SharedGameDataHumanReadable
import com.serwylo.lexica.view.QrCodeBinder
import kotlin.math.min


class NewMultiplayerActivity : AppCompatActivity() {

private lateinit var binding: NewMultiplayerBinding
private lateinit var appBitmap: Bitmap
private lateinit var webBitmap: Bitmap

override fun onCreate(savedInstanceState: Bundle?) {

Expand Down 8000 Expand Up @@ -75,28 +74,11 @@ class NewMultiplayerActivity : AppCompatActivity() {
board.add(game.board.elementAt(i))
}

val sharedGameData = SharedGameData(board, language, gameMode, SharedGameData.Type.MULTIPLAYER)
val uri = sharedGameData.serialize(SharedGameData.Platform.ANDROID)
val metrics = resources.displayMetrics
val size = min(metrics.widthPixels, metrics.heightPixels)
appBitmap = QRCodeEncoder.encodeAsBitmap(uri.toString(), size)

val webUri = sharedGameData.serialize(SharedGameData.Platform.WEB)
webBitmap = QRCodeEncoder.encodeAsBitmap(webUri.toString(), size)

Log.d(TAG, "Preparing multiplayer game: $uri")

binding.qr.setImageBitmap(appBitmap)
binding.gameModeDetails.setGameMode(gameMode)
binding.gameModeDetails.setLanguage(language)

binding.toggleQr.isEnabled = true
binding.toggleQr.isChecked = false

binding.toggleQr.setOnCheckedChangeListener { _, isChecked -> when (isChecked) {
true -> binding.qr.setImageBitmap(webBitmap)
false -> binding.qr.setImageBitmap(appBitmap)
} }
val qrCodeBinder = QrCodeBinder(this, resources, game)
qrCodeBinder.bindUI(binding.qr, binding.toggleQr)

binding.multiplayerGameNumAvailableWords.text = resources.getQuantityString(R.plurals.num_available_words_in_game__tap_to_refresh, game.maxWordCount, game.maxWordCount)
binding.multiplayerGameNumAvailableWords.setOnClickListener {
Expand All @@ -122,13 +104,13 @@ class NewMultiplayerActivity : AppCompatActivity() {
val text = """
${getString(R.string.invite__multiplayer__description)}

$uri
$qrCodeBinder.uri

${getString(R.string.invite__dont_have_lexica_installed)}

${getString(R.string.invite__dont_have_lexica_installed_web)}

$webUri
$qrCodeBinder.webUri

${getString(R.string.invite__multiplayer__game_offline)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.serwylo.lexica.ThemeManager
import com.serwylo.lexica.databinding.ShareGameLobbyBinding
import com.serwylo.lexica.db.GameMode
import com.serwylo.lexica.db.GameModeRepository
import com.serwylo.lexica.game.CharProbGenerator
import com.serwylo.lexica.game.Game
import com.serwylo.lexica.lang.Language
import com.serwylo.lexica.share.SharedGameData
Expand Down Expand Up @@ -81,7 +82,7 @@ class ShareGameLobbyActivity : AppCompatActivity() {
binding.gameModeDetails.setGameMode(gameMode)
binding.startGame.isEnabled = true

val game = Game(this, gameMode, data.language, data.board.toTypedArray())
val game = Game(this, gameMode, data.language, CharProbGenerator.BoardSeed(data.board.toTypedArray()))
binding.multiplayerGameNumAvailableWords.text = resources.getQuantityString(R.plurals.num_available_words_in_game, game.maxWordCount, game.maxWordCount)

binding.startGame.setOnClickListener { startGame(data.language, gameMode, data.board) }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.serwylo.lexica.activities.score

import android.content.Intent
import android.util.Log
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.appcompat.widget.SwitchCompat
import androidx.core.content.ContextCompat
import com.serwylo.lexica.R
import com.serwylo.lexica.game.CharProbGenerator.BoardSeed
import com.serwylo.lexica.game.Game
import com.serwylo.lexica.view.QrCodeBinder
import mehdi.sakout.fancybuttons.FancyButton

class NextRoundViewBinder(activity: ScoreActivity, parent: FrameLayout, game: Game) {

init {
Log.d("DB", "bindNextRound: calling bindNextRound")
val nextRoundView = activity.layoutInflater.inflate(R.layout.score_next_round, parent, true)
val qr = nextRoundView.findViewById<ImageView>(R.id.qr)
val toggleQr = nextRoundView.findViewById<SwitchCompat>(R.id.toggle_qr)

val nextGame = Game.generateGame(parent.context, game.gameMode, game.language, BoardSeed.fromPreviousBoard(game.board).seed)

val qrCodeBinder = QrCodeBinder(parent.context, parent.resources, nextGame)
qrCodeBinder.bindUI(qr, toggleQr)

val startNextRoundBtn = nextRoundView.findViewById<FancyButton>(R.id.start_next_round)
startNextRoundBtn.setOnClickListener {
Log.d("DB", "bindNextRound: Start Next Round clicked")

val intent = Intent("com.serwylo.lexica.action.NEW_GAME").apply {
putExtra("gameMode", nextGame.gameMode)
putExtra("lang", nextGame.language.name)
putExtra("board", nextGame.board.letters)

// todo: find out why these tags are set in the first place normally
// and why setting them in this case (with the main difference probably being the absence
// of a home activity) on some devices leads to the closing of the app.
// flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME
}

ContextCompat.startActivity(parent.context, intent, null)
activity.finish()
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class ScoreActivity : AppCompatActivity() {
if (isOnlyFoundWords) {
binding.foundWordsButton.visibility = View.GONE
binding.missedWordsButton.visibility = View.GONE
binding.multiplayerNextRound.visibility = View.GONE
binding.toolbar.title = getString(R.string.found_words)
}

Expand All @@ -106,13 +107,25 @@ class ScoreActivity : AppCompatActivity() {
binding.foundWordsButton.setOnClickListener {
binding.recyclerView.scrollToPosition(0)
binding.foundWordsButton.setBackgroundColor(buttonBackgroundColorSelected)

binding.missedWordsButton.setBackgroundColor(buttonBackgroundColor)
binding.multiplayerNextRound.setBackgroundColor(buttonBackgroundColor)
}

binding.missedWordsButton.setOnClickListener {
binding.recyclerView.scrollToPosition(1)
binding.foundWordsButton.setBackgroundColor(buttonBackgroundColor)
binding.missedWordsButton.setBackgroundColor(buttonBackgroundColorSelected)

binding.foundWordsButton.setBackgroundColor(buttonBackgroundColor)
binding.multiplayerNextRound.setBackgroundColor(buttonBackgroundColor)
}

binding.multiplayerNextRound.setOnClickListener {
binding.recyclerView.scrollToPosition(2)
binding.multiplayerNextRound.setBackgroundColor(buttonBackgroundColorSelected)

binding.foundWordsButton.setBackgroundColor(buttonBackgroundColor)
binding.missedWordsButton.setBackgroundColor(buttonBackgroundColor)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class ScoreTabAdapter extends RecyclerView.Adapter<ScoreTabViewHolder> {

private static final int VIEW_TYPE_FOUND_WORDS = 1;
private static final int VIEW_TYPE_MISSED_WORDS = 2;
private static final int VIEW_TYPE_NEXT_ROUND = 3;

private final ScoreActivity scoreActivity;
private final Game game;
Expand All @@ -31,8 +32,10 @@ public ScoreTabViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view
viewHolder.bindFoundWords(game, sorter);
} else if (viewType == VIEW_TYPE_MISSED_WORDS) {
viewHolder.bindMissedWords(game, sorter);
} else if (viewType == VIEW_TYPE_NEXT_ROUND) {
viewHolder.bindNextRound(game);
} else {
throw new IllegalArgumentException("The viewType should be either VIEW_TYPE_FOUND_WORDS or VIEW_TYPE_MISSED_WORDS, but got " + viewType);
throw new IllegalArgumentException("The viewType should be either VIEW_TYPE_FOUND_WORDS, VIEW_TYPE_MISSED_WORDS, or VIEW_TYPE_NEXT_ROUND, but got " + viewType);
}
return viewHolder;
}
Expand All @@ -45,7 +48,7 @@ public void onBindViewHolder(@NonNull ScoreTabViewHolder holder, int position) {

@Override
public int getItemCount() {
return 2;
return 3;
}

@Override
Expand All @@ -54,6 +57,8 @@ public int getItemViewType(int position) {
return VIEW_TYPE_FOUND_WORDS;
} else if (position == 1) {
return VIEW_TYPE_MISSED_WORDS;
} else if (position == 2) {
return VIEW_TYPE_NEXT_ROUND;
}

throw new IllegalArgumentException("Score activity adapter only support two items, but was asked for item at position " + position);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.serwylo.lexica.activities.score

import android.widget.FrameLayout
import androidx.recyclerview.widget.RecyclerView
import com.serwylo.lexica.game.Game

internal class ScoreTabViewHolder(private val activity: ScoreActivity, private val parent: FrameLayout) : RecyclerView.ViewHolder(parent) {
fun bindFoundWords(game: Game, sorter: Sorter) {
FoundWordsViewBinder(activity, parent, game, sorter)
}

fun bindMissedWords(game: Game, sorter: Sorter) {
MissedWordsViewBinder(activity, parent, game, sorter)
}

fun bindNextRound(game: Game) {
NextRoundViewBinder(activity, parent, game)
}
}
36 changes: 27 additions & 9 deletions app/src/main/java/com/serwylo/lexica/game/Game.java
368B
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Random;

public class Game implements Synchronizer.Counter {

Expand Down Expand Up @@ -161,7 +162,9 @@ public Game(Context context, GameSaver saver) {
}
}

public Game(Context context, GameMode gameMode, Language language, String[] boardLetters) {


public Game(Context context, GameMode gameMode, Language language, CharProbGenerator.BoardSeed boardSeed) {
this.language = language;
this.gameMode = gameMode;
status = GameStatus.GAME_STARTING;
Expand All @@ -170,22 +173,20 @@ public Game(Context context, GameMode gameMode, Language language, String[] boar

loadSounds(context);

String lettersFileName = language.getLetterDistributionFileName();
int id = context.getResources().getIdentifier("raw/" + lettersFileName.substring(0, lettersFileName.lastIndexOf('.')), null, context.getPackageName());
CharProbGenerator charProbs = new CharProbGenerator(context.getResources().openRawResource(id), getLanguage());
CharProbGenerator charProbs = getCharProbGenerator(context);
Board board;

switch (gameMode.getBoardSize()) {
case 16:
board = boardLetters == null ? charProbs.generateFourByFourBoard() : new FourByFourBoard(boardLetters);
board = charProbs.generateFourByFourBoard(boardSeed);
break;

case 25:
board = boardLetters == null ? charProbs.generateFiveByFiveBoard() : new FiveByFiveBoard(boardLetters);
board = charProbs.generateFiveByFiveBoard(boardSeed);
break;

case 36:
board = boardLetters == null ? charProbs.generateSixBySixBoard() : new SixBySixBoard(boardLetters);
board = charProbs.generateSixBySixBoard(boardSeed);
break;

default:
Expand All @@ -201,16 +202,33 @@ public Game(Context context, GameMode gameMode, Language language, String[] boar
initializeWeights();
}

@NonNull
private CharProbGenerator getCharProbGenerator(Context context) {
String lettersFileName = language.getLetterDistributionFileName();
int id = context.getResources().getIdentifier("raw/" + lettersFileName.substring(0, lettersFileName.lastIndexOf('.')), null, context.getPackageName());
CharProbGenerator charProbs = new CharProbGenerator(context.getResources().openRawResource(id), getLanguage());
return charProbs;
}

/**
* TODO: This is not a very pure function. The Game constructor loads preferences, reads sounds from disk, and probably does
* many other things. This should be refactored so that it is more predictable what happens.
*/
public static Game generateGame(@NonNull Context context, @NonNull GameMode gameMode, @NonNull Language language) {
Game bestGame = new Game(context, gameMode, language, null);
return generateGame(context, gameMode, language, null);
}

public static Game generateGame(@NonNull Context context, @NonNull GameMode gameMode, @NonNull Language language, Long seed) {
Game bestGame = new Game(context, gameMode, language, new CharProbGenerator.BoardSeed(seed));
Board lastBoard = bestGame.board; // needed so we still receive deterministic boards, even when skipping tries

int numAttempts = 0;
while (bestGame.getMaxWordCount() < 45 && numAttempts < 5) {
Log.d(TAG, "Generating another board, because the previous one only had " + bestGame.getMaxWordCount() + " words, but we want at least 45. Will give up after 5 tries.");
Game nextAttempt = new Game(context, gameMode, language, null);

Game nextAttempt = new Game(context, gameMode, language, CharProbGenerator.BoardSeed.fromPreviousBoard(lastBoard));
lastBoard = nextAttempt.getBoard();

if (nextAttempt.getMaxWordCount() > bestGame.getMaxWordCount()) {
bestGame = nextAttempt;
}
Expand Down
Loading
0