Skip to content

Commit b72b830

Browse files
authored
Merge pull request #15 from patjackson52/bugfix/gameResults-bug
fix game results not showing
2 parents 06693a4 + 113aa5f commit b72b830

File tree

10 files changed

+382
-43
lines changed

10 files changed

+382
-43
lines changed

app/src/main/java/com/willowtreeapps/namegame/store/QuestionFragment.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class QuestionFragment : Fragment(), CoroutineScope, QuestionView, MainActivity.
182182

183183
private fun fadeNextButton(after: () -> Unit) {
184184
btn_next.animate().alpha(0f).withEndAction {
185+
lastCorrectBtn?.alpha = 0f
185186
btn_next.visibility = View.GONE
186187
after()
187188
}

common/src/commonMain/kotlin/com/willowtreeapps/common/GameEngine.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class GameEngine(navigator: Navigator, application: Any = Any(),
1818
val vibrateUtil = VibrateUtil(application)
1919

2020
val appStore by lazy {
21-
SimpleStore(AppState.INITIAL_STATE, reducer)
21+
SimpleStore(AppState.INITIAL_STATE, ::reducer)
2222
.applyMiddleware(::thunkMiddleware,
2323
viewEffectsMiddleware::dispatch,
2424
navigationMiddleware::dispatch)

common/src/commonMain/kotlin/com/willowtreeapps/common/Reducers.kt

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,47 @@
11
package com.willowtreeapps.common
22

3-
import com.beyondeye.reduks.ReducerFn
43
import com.willowtreeapps.common.Actions.*
54
import com.willowtreeapps.common.repo.Profile
65
import com.willowtreeapps.common.util.TimeUtil
76
import kotlin.math.abs
87
import kotlin.random.Random
98

109
/**
11-
* Reducers and functions used by reducers are in this file. Functions must be pure functiuns without
10+
* Reducers and functions used by reducers are in this file. Functions must be pure functions without
1211
* side effects.
1312
*/
14-
15-
val reducer = ReducerFn<AppState> { state, action ->
16-
when (action) {
17-
is FetchingProfilesStartedAction -> state.copy(isLoadingProfiles = true)
18-
is FetchingProfilesSuccessAction -> {
19-
val rounds = generateRounds(action.profiles, state.numQuestions)
20-
state.copy(isLoadingProfiles = false, profiles = action.profiles, questions = rounds)
21-
}
22-
is FetchingProfilesFailedAction -> state.copy(isLoadingProfiles = false, errorLoadingProfiles = true, errorMsg = action.message)
23-
is NamePickedAction -> {
24-
val status = if (state.currentQuestionProfile().matches(action.name)) {
25-
Question.Status.CORRECT
26-
} else {
27-
Question.Status.INCORRECT
13+
fun reducer(state: AppState, action: Any): AppState =
14+
when (action) {
15+
is FetchingProfilesStartedAction -> state.copy(isLoadingProfiles = true)
16+
is FetchingProfilesSuccessAction -> {
17+
val rounds = generateRounds(action.profiles, state.numQuestions)
18+
state.copy(isLoadingProfiles = false, profiles = action.profiles, questions = rounds)
19+
}
20+
is FetchingProfilesFailedAction -> state.copy(isLoadingProfiles = false, errorLoadingProfiles = true, errorMsg = action.message)
21+
is NamePickedAction -> {
22+
val status = if (state.currentQuestionProfile().matches(action.name)) {
23+
Question.Status.CORRECT
24+
} else {
25+
Question.Status.INCORRECT
26+
}
27+
val newQuestions = state.questions.toMutableList()
28+
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = action.name, status = status)
29+
state.copy(questions = newQuestions, waitingForNextQuestion = true)
30+
}
31+
is NextQuestionAction -> state.copy(waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
32+
is GameCompleteAction -> state.copy(waitingForResultsTap = true, waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
33+
is StartOverAction, is ResetGameStateAction -> AppState.INITIAL_STATE
34+
is StartQuestionTimerAction -> state.copy(questionClock = action.initialValue)
35+
is DecrementCountDownAction -> state.copy(questionClock = state.questionClock - 1)
36+
is TimesUpAction -> {
37+
val status = Question.Status.TIMES_UP
38+
val newQuestions = state.questions.toMutableList()
39+
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = "", status = status)
40+
state.copy(questions = newQuestions, waitingForNextQuestion = true, questionClock = -1)
2841
}
29-
val newQuestions = state.questions.toMutableList()
30-
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = action.name, status = status)
31-
state.copy(questions = newQuestions, waitingForNextQuestion = true)
32-
}
33-
is NextQuestionAction -> state.copy(waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
34-
is GameCompleteAction -> state.copy(waitingForResultsTap = true, waitingForNextQuestion = false, currentQuestionIndex = state.currentQuestionIndex + 1)
35-
is StartOverAction, is ResetGameStateAction -> AppState.INITIAL_STATE
36-
is StartQuestionTimerAction -> state.copy(questionClock = action.initialValue)
37-
is DecrementCountDownAction -> state.copy(questionClock = state.questionClock - 1)
38-
is TimesUpAction -> {
39-
val status = Question.Status.TIMES_UP
40-
val newQuestions = state.questions.toMutableList()
41-
newQuestions[state.currentQuestionIndex] = newQuestions[state.currentQuestionIndex].copy(answerName = "", status = status)
42-
state.copy(questions = newQuestions, waitingForNextQuestion = true, questionClock = -1)
43-
}
4442

45-
else -> throw AssertionError("Action ${action::class.simpleName} not handled")
46-
}
47-
}
43+
else -> throw AssertionError("Action ${action::class.simpleName} not handled")
44+
}
4845

4946
fun generateRounds(profiles: List<Profile>, n: Int): List<Question> =
5047
profiles.takeRandomDistinct(n)

common/src/commonMain/kotlin/com/willowtreeapps/common/repo/KtorProfilesRepository.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ class ProfileListHolder(val profiles: List<Profile>)
6666

6767
class ProfileListHolderSerializer : KSerializer<ProfileListHolder> {
6868

69-
override val descriptor = object : SerialClassDescImpl("Inner") {
70-
}
69+
override val descriptor = object : SerialClassDescImpl("Inner") {}
7170

7271
override fun deserialize(input: Decoder): ProfileListHolder {
7372
val list = input.decodeSerializableValue(Profile.serializer().list)

common/src/commonMain/kotlin/com/willowtreeapps/common/ui/GameResultsPresenter.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package com.willowtreeapps.common.ui
22

3+
import com.beyondeye.reduks.SelectorSubscriberFn
34
import com.beyondeye.reduks.Store
4-
import com.beyondeye.reduks.StoreSubscriber
5-
import com.beyondeye.reduks.StoreSubscriberFn
65
import com.willowtreeapps.common.Actions
76
import com.willowtreeapps.common.AppState
87
import com.willowtreeapps.common.Presenter
8+
import com.willowtreeapps.common.boundary.toGameResultsViewState
99

1010
class GameResultsPresenter(val store: Store<AppState>) : Presenter<GameResultsView>() {
11-
override fun makeSubscriber(): StoreSubscriber<AppState> {
12-
return StoreSubscriberFn { }
11+
override fun makeSubscriber() = SelectorSubscriberFn(store) {
12+
withAnyChange { view?.showResults(state.toGameResultsViewState()) }
1313
}
1414

1515
fun startOverTapped() {

common/src/commonMain/kotlin/com/willowtreeapps/common/ui/PresenterFactory.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import kotlin.coroutines.CoroutineContext
88
* PresenterFactory that creates presenters for all views in the application.
99
* Each view must attach/detach itself as it becomes visible/not visible.
1010
* Attaching returns a presenter to the view.
11+
* PresenterFactory subscribes to changes in state, and passes state to presenters.
1112
*/
1213
internal class PresenterFactory(private val gameEngine: GameEngine, networkContext: CoroutineContext) : StoreSubscriber<AppState> {
1314

@@ -21,7 +22,7 @@ internal class PresenterFactory(private val gameEngine: GameEngine, networkConte
2122
private val gameResultsPresenter by lazy { GameResultsPresenter(gameEngine.appStore) }
2223

2324

24-
fun <T : View?> attachView(view: T): Presenter<out View?> {
25+
fun <T : View> attachView(view: T): Presenter<out View?> {
2526
Logger.d("AttachView: $view")
2627
if (subscription == null) {
2728
subscription = gameEngine.appStore.subscribe(this)

jvmcli/build.gradle

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
apply plugin: 'application'
2+
apply plugin: 'kotlin'
3+
4+
dependencies {
5+
implementation fileTree(dir: 'libs', include: ['*.jar'])
6+
implementation project(':common')
7+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
8+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
9+
implementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.26'
10+
implementation "io.ktor:ktor-client-okhttp:$ktorVersion"
11+
implementation "io.ktor:ktor-client-json-jvm:$ktorVersion"
12+
}
13+
14+
task runMain(type: JavaExec) {
15+
main = 'com.willowtreeapps.namegame.jvmcli.Main'
16+
classpath = sourceSets.main.runtimeClasspath
17+
}
18+
19+
run {
20+
systemProperties = System.properties
21+
}
22+
23+
24+
sourceCompatibility = "8"
25+
targetCompatibility = "8"
26+
buildscript {
27+
ext.kotlin_version = '1.3.30-eap-125'
28+
repositories {
29+
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
30+
mavenCentral()
31+
}
32+
dependencies {
33+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
34+
}
35+
}
36+
repositories {
37+
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
38+
mavenCentral()
39+
}
40+
compileKotlin {
41+
kotlinOptions {
42+
jvmTarget = "1.8"
43+
}
44+
}
45+
compileTestKotlin {
46+
kotlinOptions {
47+
jvmTarget = "1.8"
48+
}
49+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
Created by Eric Mikulin, 2015
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
/*
18+
Image to ASCII Art Converter
19+
Designed for a SWCHS CompSci Club fortnight challenge
20+
Challenge Components: Speed, Input variety and Output Aesthetics
21+
*/
22+
23+
package com.willowtreeapps.namegame.jvmcli;
24+
25+
//Import the Packages
26+
27+
import java.awt.image.BufferedImage;
28+
import java.io.IOException;
29+
import java.net.URL;
30+
import java.util.HashMap;
31+
import java.util.Map;
32+
33+
import javax.imageio.ImageIO;
34+
35+
public class ImageConverter implements Runnable {
36+
//Create a map to map between darknesses (int) and characters (ASCII based on darkness). See mapit(); for detail
37+
static Map<Integer, Character> asciiMap = new HashMap<Integer, Character>();
38+
//Create the image and link
39+
static BufferedImage image;
40+
static URL link;
41+
42+
public static void displayImage(String url) throws IOException {
43+
//Create the thread for loading the image
44+
ImageConverter load = new ImageConverter(); //create another instance of this class
45+
Thread loadThread = new Thread(load); //Turn that into a thread
46+
47+
//Map characters to integers
48+
mapit();
49+
50+
link = new URL(url);
51+
loadThread.start(); //Start the thread
52+
53+
//Ask for the "Line Skip Coefficient"
54+
//Basically, this is the amount the x and y values of the coordinate increase each time. Larger = smaller image.
55+
//Anything above 2 usually doesn't work too well
56+
int skipC = 2;
57+
58+
59+
//Test if the thread is still running, then wait for it to finish if it is
60+
if (loadThread.isAlive()) {
61+
try {
62+
loadThread.join(); //Wait for thread
63+
} catch (InterruptedException e) {
64+
e.printStackTrace();
65+
}
66+
}
67+
68+
//Get the length and width of the image, storx`e as integer values
69+
int imgWidth = image.getWidth();
70+
int imgHeight = image.getHeight();
71+
72+
73+
//This is the conversion loop, goes through every x for each y line
74+
for (int y = 0; y < imgHeight; y += 2 * skipC) {
75+
for (int x = 0; x < imgWidth; x += skipC) {
76+
System.out.print(convert(image.getRGB(x, y)));
77+
}
78+
System.out.println();
79+
}
80+
}
81+
82+
//Converts the RGB int value to a char, based on the amount of color in the pixel
83+
private static char convert(int value) {
84+
//Grab the three values for each red, green and blue (and alpha)
85+
int alpha = (value >> 24) & 0xFF;
86+
int red = (value >> 16) & 0xFF;
87+
int green = (value >> 8) & 0xFF;
88+
int blue = (value) & 0xFF;
89+
90+
//Covert to a unified integer value between 0 and 26.
91+
//This is done by averaging, then dividing by 10 (RGB values range from 0 to 255)
92+
int darkness = ((int) ((0.21 * red) + (0.72 * green) + (0.07 * blue) / 3) / 10);
93+
94+
//If alpha is completely clear, assume white
95+
if (alpha == 0)
96+
darkness = 26;
97+
98+
//Output the respective char, grabbing it from the hashmap
99+
char chart = asciiMap.get(darkness);
100+
return chart;
101+
}
102+
103+
//This function creates the actual link from the integers and chars
104+
private static void mapit() {
105+
//Map an integer darkness value to an ASCII character
106+
//The value of darkness for the chars I determined from some other random Internet source
107+
asciiMap.put(0, '@');
108+
asciiMap.put(1, '@');
109+
asciiMap.put(2, '@');
110+
asciiMap.put(3, '@');
111+
asciiMap.put(4, '@');
112+
113+
asciiMap.put(5, '@');
114+
asciiMap.put(6, 'N');
115+
asciiMap.put(7, '%');
116+
asciiMap.put(8, 'W');
117+
asciiMap.put(9, '$');
118+
119+
asciiMap.put(10, 'D');
120+
asciiMap.put(11, 'd');
121+
asciiMap.put(12, 'x');
122+
asciiMap.put(13, '6');
123+
asciiMap.put(14, 'E');
124+
125+
asciiMap.put(15, '5');
126+
asciiMap.put(16, '{');
127+
asciiMap.put(17, 's');
128+
asciiMap.put(18, '?');
129+
asciiMap.put(19, '!');
130+
131+
asciiMap.put(20, ';');
132+
asciiMap.put(21, '"');
133+
asciiMap.put(22, ':');
134+
asciiMap.put(23, '_');
135+
asciiMap.put(24, '\'');
136+
137+
asciiMap.put(25, '`');
138+
asciiMap.put(26, ' ');
139+
}
140+
141+
//The function run for when you need multi-thread
142+
public void run() {
143+
try {
144+
image = ImageIO.read(link); //Load the image from the web
145+
} catch (IOException e) {
146+
e.printStackTrace();
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)