Commit fa315715 authored by fpeterfalvi's avatar fpeterfalvi
Browse files

Generate new question list function implemented

Server user can restrict the list of questions from the full database to a limited number of random questions with selecting which topics to include and providing the maximum number of questions per topic.
parent 720f0ce0
......@@ -30,4 +30,5 @@ dependencies {
implementation 'com.github.rustamg:file-dialogs:1.0'
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.github.satyan:sugar:1.4'
implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'
}
......@@ -11,7 +11,12 @@
<uses-permission
android:name="android.permission.INTERNET"
android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:required="true" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:required="true" />
<application
android:allowBackup="true"
......
......@@ -22,13 +22,18 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import onlab.kvizserver.model.PlayerAnswer;
import onlab.kvizserver.model.Question;
public class GameActivity extends AppCompatActivity implements GameControlFragment.OnFragmentInteractionListener,
QuestionListFragment.OnFragmentInteractionListener, FileDialog.OnFileSelectedListener {
QuestionListFragment.OnFragmentInteractionListener, FileDialog.OnFileSelectedListener,
QuestionListGeneratorDialogFragment.OnFragmentInteractionListener {
private Question question = null;
private int numberOfPlayers;
......@@ -68,9 +73,7 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
inputs.add(new BufferedReader(new InputStreamReader(ClientHolder.get(i).getClientsocket().getInputStream())));
PrintWriter output = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(ClientHolder.get(i).getClientsocket().getOutputStream())), true);
output.println("$$$$");
outputs.add(output);
output.println("GameStarted##normal");
}
} catch (IOException e) {
e.printStackTrace();
......@@ -103,6 +106,8 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
}
public void run() {
output.println("$$$$");
output.println("GameStarted##normal");
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
......@@ -162,7 +167,7 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
@Override
public void nextQuestionButtonClicked(int timeLimit) {
gameControlFragment.setCorrectAnswerButtonEnabled(true);
questionListFragment.selecetedQuestionDisplayed();
questionListFragment.selectedQuestionDisplayed();
gameControlFragment.setNextQuestionButtonEnabled(false);
questionString = question.getQuestionText();
......@@ -258,4 +263,59 @@ public class GameActivity extends AppCompatActivity implements GameControlFragme
}
}
@Override
public void generateQuestionList(List<String> topics, int numberOfMultipleChoice, int numberOfGuess, boolean onlyEnabled) {
Log.d("questionList", "Megvan a kérdéslista");
List<Question> questions = Question.listAll(Question.class);
// disabled kérdések eltávolítása, ha csak enabled kérdésekből kell válogatni
if (onlyEnabled) {
Iterator<Question> it = questions.iterator();
while( it.hasNext() ) {
Question q = it.next();
if(!q.isEnabled())
it.remove();
}
}
// megfelelő számú kérdés kiválogatása
Collections.shuffle(questions);
Map<String, Integer> selectedMultiple = new HashMap<>();
Map<String, Integer> selectedGuess = new HashMap<>();
for (String topic : topics) {
selectedMultiple.put(topic, 0);
selectedGuess.put(topic, 0);
}
Iterator<Question> it = questions.iterator();
while( it.hasNext() ) {
Question q = it.next();
boolean selected = false;
String topic = q.getTopic();
if(q.getType() == Question.MULTIPLE_CHOICE &&
selectedMultiple.get(topic) != null && selectedMultiple.get(topic) < numberOfMultipleChoice) {
selected = true;
selectedMultiple.put(topic, selectedMultiple.get(topic) + 1);
} else if (q.getType() == Question.GUESS &&
selectedGuess.get(topic) != null && selectedGuess.get(topic) < numberOfGuess) {
selected = true;
selectedGuess.put(topic, selectedGuess.get(topic) + 1);
} else {
q.setCurrentIndex(0);
q.save();
it.remove();
}
}
// kérdések véletleszerű sorrendbe rakása és indexek hozzárendelése
Collections.shuffle(questions);
for (int i=0;i<questions.size();i++) {
Question question = questions.get(i);
question.setCurrentIndex(i + 1);
question.save();
}
// QuestionListFragment frissítése
questionListFragment.refreshQuestionList();
}
}
......@@ -121,7 +121,7 @@ public class GameControlFragment extends Fragment {
public void displayMultipleChoiceQuestion(String questionTextString, List<String> answers, String correctAnswerString) {
questionText.setText(questionTextString);
correctAnswerTextView.setText(correctAnswerString);
correctAnswerTextView.setText("Correct answer: " + correctAnswerString);
for (int i=0;i<4;i++) {
answerTextViews.get(i).setVisibility(View.VISIBLE);
answerTextViews.get(i).setText(answers.get(i));
......
package onlab.kvizserver;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import onlab.kvizserver.model.ClientModel;
......@@ -106,10 +97,14 @@ public class LobbyActivity extends AppCompatActivity {
public void onClick(View view) {
if (gameMode.equals("quizup") && (clients.size() != 2)) {
Toast.makeText(getApplicationContext(), "QuizUp mode requires exactly 2 players!", Toast.LENGTH_LONG).show();
} else if (gameMode.equals("normal") && (clients.size() == 0)) {
Toast.makeText(getApplicationContext(), "Game requires at least one player!", Toast.LENGTH_LONG).show();
} else {
exit = false;
serverThread.interrupt();
commThread.interrupt();
if (commThread != null) {
commThread.interrupt();
}
ClientHolder.addAll(clients);
Intent intent;
if (gameMode.equals("normal")) {
......@@ -401,10 +396,6 @@ public class LobbyActivity extends AppCompatActivity {
}
enum Operation {
ADD_CLIENT, REMOVE_CLIENT;
}
......
......@@ -7,6 +7,7 @@ import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
......@@ -35,6 +36,8 @@ public class MainActivity extends AppCompatActivity implements FileDialog.OnFile
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Button StartLobbyBtn = (Button) findViewById(R.id.StartLobby);
final EditText txtName = (EditText) findViewById(R.id.txtName);
Button ChooseQuestionFileBtn = (Button) findViewById(R.id.ChooseQuestionFile);
......
package onlab.kvizserver;
public enum Operation {
ADD_CLIENT, REMOVE_CLIENT;
}
......@@ -42,7 +42,7 @@ public class QuestionListAdapter extends RecyclerView.Adapter<QuestionListAdapte
public void onBindViewHolder(final QuestionViewHolder holder, final int position) {
final Question item = items.get(position);
holder.indexOfQuestionTextView.setText(Integer.toString(position + 1));
holder.questionTextTextView.setText(item.getQuestionText());
holder.questionTextTextView.setText("[" + item.getTopic() + "]\n" + item.getQuestionText());
String answersString = item.getCorrectAnswer();
if (item.getType() == Question.MULTIPLE_CHOICE) {
List<String> otherAnswers = item.getOtherAnswers();
......@@ -124,8 +124,15 @@ public class QuestionListAdapter extends RecyclerView.Adapter<QuestionListAdapte
int index = selected;
if (index != -1) {
selected = -1;
items.get(index).setEnabled(false);
Question question = items.get(index);
question.setEnabled(false);
question.save();
notifyItemChanged(index);
}
}
public void refreshCompleteList(List<Question> questions) {
items = questions;
notifyDataSetChanged();
}
}
package onlab.kvizserver;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
......@@ -61,12 +66,24 @@ public class QuestionListFragment extends Fragment {
exportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
SaveFileDialog dialog = new SaveFileDialog();
dialog.show(getActivity().getSupportFragmentManager(), SaveFileDialog.class.getName());
}
});
Button generateButton = (Button) getView().findViewById(R.id.GenerateButton);
generateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.addToBackStack(null);
DialogFragment newFragment = QuestionListGeneratorDialogFragment.newInstance();
newFragment.show(ft, "QuestionListGeneratorDialogFragment");
}
});
}
@Override
......@@ -98,7 +115,7 @@ public class QuestionListFragment extends Fragment {
recyclerView.setAdapter(adapter);
}
public void selecetedQuestionDisplayed() {
public void selectedQuestionDisplayed() {
adapter.deselectActualQuestion();
}
......@@ -118,4 +135,9 @@ public class QuestionListFragment extends Fragment {
Collections.sort(questions);
}
public void refreshQuestionList() {
initQuestionList();
adapter.refreshCompleteList(questions);
}
}
package onlab.kvizserver;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import onlab.kvizserver.model.Question;
public class QuestionListGeneratorDialogFragment extends DialogFragment {
private OnFragmentInteractionListener mListener;
List<String> topicList;
List<CheckBox> checkBoxes = new ArrayList<>();
public QuestionListGeneratorDialogFragment() {
// Required empty public constructor
}
public static QuestionListGeneratorDialogFragment newInstance() {
QuestionListGeneratorDialogFragment fragment = new QuestionListGeneratorDialogFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_question_list_generator_dialog, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
LinearLayout topicsLinearLayout = (LinearLayout) getView().findViewById(R.id.TopicsLinearLayout);
final EditText numberOfMultipleChoiceEditText = (EditText) getView().findViewById(R.id.NumberOfMultipleChoiceEditText);
final EditText numberOfGuessEditText = (EditText) getView().findViewById(R.id.NumberOfGuessEditText);
final CheckBox onlyEnabledQuestionsCheckBox = (CheckBox) getView().findViewById(R.id.OnlyEnabledQuestionsCheckBox);
Button generateButtonOnDialog = (Button) getView().findViewById(R.id.GenerateButtonOnDialog);
List<Question> allQuestions = Question.listAll(Question.class);
topicList = Question.getTopicList(allQuestions);
for (String topic : topicList) {
LinearLayout topicLinearLayout = new LinearLayout(getContext());
topicLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
CheckBox topicCheckBox = new CheckBox(getContext());
checkBoxes.add(topicCheckBox);
TextView topicNameTextView = new TextView(getContext());
topicNameTextView.setText(topic);
topicLinearLayout.addView(topicCheckBox);
topicLinearLayout.addView(topicNameTextView);
topicsLinearLayout.addView(topicLinearLayout);
}
generateButtonOnDialog.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
restrictTopicList();
int numberOfMultipleChoice;
try {
numberOfMultipleChoice = Integer.parseInt(numberOfMultipleChoiceEditText.getText().toString());
} catch (NumberFormatException e) {
numberOfMultipleChoice = 0;
}
int numberOfGuess;
try {
numberOfGuess = Integer.parseInt(numberOfGuessEditText.getText().toString());
} catch (NumberFormatException e) {
numberOfGuess = 0;
}
mListener.generateQuestionList(topicList, numberOfMultipleChoice, numberOfGuess,
onlyEnabledQuestionsCheckBox.isChecked());
dismiss();
}
});
}
//a ki nem jelölt topicok kidobása
private void restrictTopicList() {
for (int i=checkBoxes.size()-1;i>=0;i--) {
if (!checkBoxes.get(i).isChecked()) {
topicList.remove(i);
}
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void generateQuestionList(List<String> topics, int numberOfMultipleChoice, int numberOfGuess, boolean onlyEnabled);
}
}
......@@ -6,7 +6,9 @@ import com.orm.SugarRecord;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Question extends SugarRecord implements Comparable<Question> {
private String topic;
......@@ -97,6 +99,10 @@ public class Question extends SugarRecord implements Comparable<Question> {
return currentIndex;
}
public void setCurrentIndex(int currentIndex) {
this.currentIndex = currentIndex;
}
@Override
public int compareTo(@NonNull Question question) {
return this.currentIndex - question.currentIndex;
......@@ -116,4 +122,14 @@ public class Question extends SugarRecord implements Comparable<Question> {
line += "\t" + (enabled ? "enabled" : "disabled") + "\t" + currentIndex;
return line;
}
public static List<String> getTopicList(List<Question> questions) {
Set<String> topicSet = new HashSet<>();
for (Question question : questions) {
topicSet.add(question.getTopic());
}
List<String> topicList = new ArrayList<>(topicSet);
Collections.sort(topicList);
return topicList;
}
}
......@@ -15,7 +15,6 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/GenerateButton"
android:enabled="false"
android:text="Generate new list"/>
<Button
......
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".QuestionListGeneratorDialogFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Topics"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/TopicsLinearLayout">
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Multiple choice questions per topic"
android:layout_marginTop="20dp"/>
<EditText
android:layout_width="30dp"
android:layout_height="wrap_content"
android:id="@+id/NumberOfMultipleChoiceEditText"
android:inputType="number"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Guess questions per topic"
android:layout_marginTop="20dp"/>
<EditText
android:layout_width="30dp"
android:layout_height="wrap_content"
android:id="@+id/NumberOfGuessEditText"
android:inputType="number"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/OnlyEnabledQuestionsCheckBox"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Only enabled questions"/>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Generate"
android:id="@+id/GenerateButtonOnDialog"/>
</LinearLayout>
</ScrollView>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment