Prototype ready; Core functionality implemented

This commit is contained in:
Caesar2011
2017-04-05 19:46:44 +02:00
parent 23073a8841
commit 4d2a472686
35 changed files with 1561 additions and 822 deletions

1
.idea/gradle.xml generated
View File

@@ -5,7 +5,6 @@
<GradleProjectSettings> <GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.14.1" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

16
.idea/misc.xml generated
View File

@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="EntryPointsManager"> <component name="EntryPointsManager">
<entry_points version="2.0" /> <entry_points version="2.0">
<entry_point TYPE="method" FQNAME="de.hwr_berlin.it14.postgrachelor.Types.HighscoresCategories int getId()" />
</entry_points>
</component> </component>
<component name="NullableNotNullManager"> <component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" /> <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
@@ -27,17 +29,7 @@
</value> </value>
</option> </option>
</component> </component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8 (1)" project-jdk-type="JavaSDK">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8 (2)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

1
app/.gitignore vendored
View File

@@ -1 +0,0 @@
/build

View File

@@ -24,9 +24,9 @@ dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
compile 'com.android.support:gridlayout-v7:25.3.0' compile 'com.android.support:gridlayout-v7:25.3.1'
compile 'com.android.support:appcompat-v7:25.3.0' compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.0' compile 'com.android.support:design:25.3.1'
compile 'com.android.support:support-v4:25.3.0' compile 'com.android.support:support-v4:25.3.1'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
} }

View File

@@ -11,14 +11,18 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:launchMode="singleInstance"
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:windowSoftInputMode="adjustResize" android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="postgrachelor" <data android:scheme="postgrachelor"
android:host="postgrachelor" /> android:host="postgrachelor" />
</intent-filter> </intent-filter>

View File

@@ -0,0 +1,26 @@
package de.hwr_berlin.it14.postgrachelor.Exceptions;
/**
* Created by sebastian on 25.03.17.
* Exception to indicate a not instantiated service
*/
public class NoCurrentQuestionException extends Exception {
private static final long serialVersionUID = 1997753363232807010L;
public NoCurrentQuestionException() {
super();
}
public NoCurrentQuestionException(String message) {
super(message);
}
public NoCurrentQuestionException(Throwable cause) {
super(cause);
}
public NoCurrentQuestionException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,26 @@
package de.hwr_berlin.it14.postgrachelor.Exceptions;
/**
* Created by sebastian on 25.03.17.
* Exception to indicate a not instantiated service
*/
public class NotLoggedInException extends Exception {
private static final long serialVersionUID = 1997753363232807010L;
public NotLoggedInException() {
super();
}
public NotLoggedInException(String message) {
super(message);
}
public NotLoggedInException(Throwable cause) {
super(cause);
}
public NotLoggedInException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,7 +1,5 @@
package de.hwr_berlin.it14.postgrachelor; package de.hwr_berlin.it14.postgrachelor;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.app.Fragment; import android.app.Fragment;
import android.util.Log; import android.util.Log;
@@ -17,24 +15,11 @@ import de.hwr_berlin.it14.postgrachelor.Services.LoginService;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link LoginFragment.OnLoginFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link LoginFragment#newInstance} factory method to * Use the {@link LoginFragment#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */
public class LoginFragment extends Fragment { public class LoginFragment extends Fragment {
public static final String NAME = "LOGIN_FRAGMENT"; public static final String NAME = "LOGIN_FRAGMENT";
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnLoginFragmentInteractionListener mListener;
public LoginFragment() { public LoginFragment() {
// Required empty public constructor // Required empty public constructor
@@ -44,29 +29,15 @@ public class LoginFragment extends Fragment {
* Use this factory method to create a new instance of * Use this factory method to create a new instance of
* this fragment using the provided parameters. * this fragment using the provided parameters.
* *
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment LoginFragment. * @return A new instance of fragment LoginFragment.
*/ */
// TODO: Rename and change types and number of parameters public static LoginFragment newInstance() {
public static LoginFragment newInstance(String param1, String param2) {
LoginFragment fragment = new LoginFragment(); LoginFragment fragment = new LoginFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@@ -89,43 +60,4 @@ public class LoginFragment extends Fragment {
return layout; return layout;
} }
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onLoginFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnLoginFragmentInteractionListener) {
mListener = (OnLoginFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnLoginFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
interface OnLoginFragmentInteractionListener {
// TODO: Update argument type and name
void onLoginFragmentInteraction(Uri uri);
}
} }

View File

@@ -2,38 +2,31 @@ package de.hwr_berlin.it14.postgrachelor;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.support.design.widget.NavigationView; import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.TextView;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException; import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException;
import de.hwr_berlin.it14.postgrachelor.Services.GameService;
import de.hwr_berlin.it14.postgrachelor.Services.HighscoreService;
import de.hwr_berlin.it14.postgrachelor.Services.LoginService; import de.hwr_berlin.it14.postgrachelor.Services.LoginService;
public class MainActivity extends AppCompatActivity public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, implements NavigationView.OnNavigationItemSelectedListener {
MainFragment.OnMainFragmentInteractionListener,
LoginFragment.OnLoginFragmentInteractionListener,
QuestionEndFragment.OnQuestionEndFragmentInteractionListener,
QuestionFragment.OnQuestionFragmentInteractionListener,
QuestionStartFragment.OnQuestionStartFragmentInteractionListener {
FragmentManager myFragmentManager;
MainFragment mainFragment;
LoginFragment loginFragment; private static final String NAME = "MainActivity";
QuestionStartFragment questionStartFragment; private FragmentManager myFragmentManager;
QuestionEndFragment questionEndFragment; private MainFragment mainFragment;
QuestionFragment questionFragment; private LoginFragment loginFragment;
boolean listenerAdded; private QuestionEndFragment questionEndFragment;
private QuestionFragment questionFragment;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -43,69 +36,31 @@ public class MainActivity extends AppCompatActivity
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
/*FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});*/
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
// content // content
myFragmentManager = getFragmentManager(); myFragmentManager = getFragmentManager();
mainFragment = MainFragment.newInstance("a", "b"); mainFragment = MainFragment.newInstance();
loginFragment = LoginFragment.newInstance("a", "b"); loginFragment = LoginFragment.newInstance();
questionEndFragment = QuestionEndFragment.newInstance("a", "b"); questionEndFragment = QuestionEndFragment.newInstance();
questionStartFragment = QuestionStartFragment.newInstance("a", "b"); questionFragment = QuestionFragment.newInstance();
questionFragment = QuestionFragment.newInstance("a", "b");
/*Log.d("Activity fragment", "test2");
JsonRequestPG requester = new JsonRequestPG("register.php", null, this, new JsonRequestPG.AsyncResponse() {
@Override
public void processFinish(JSONObject output) {
Log.d("Activity fragment", "output");
Log.d("Activity fragment", output.toString());
}
@Override
public void processError(int status, String message) {
Log.d("Activity fragment", "error");
Log.d("Activity fragment", "status: "+status+" - message: "+message);
}
});
requester.execute();*/
LoginService.instantiate(this); LoginService.instantiate(this);
listenerAdded = false; HighscoreService.instantiate(this);
GameService.initialize(this);
} }
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
final MainActivity that = this; final MainActivity that = this;
if (!listenerAdded) { LoginService.addLoginEventListener(NAME, new LoginService.OnLoginEventListener() {
LoginService.addLoginEventListener(new LoginService.OnLoginEventListener() {
@Override @Override
public void onLoginEvent(String name, String uid) { public void onLoginEvent(String name, String uid) {
Log.d("Activity fragment", "onLogin - name: " + name + " - uid: " + uid); Log.d("Activity fragment", "onLogin - name: " + name + " - uid: " + uid);
NavigationView nav_view = (NavigationView) that.findViewById(R.id.nav_view); /*NavigationView nav_view = (NavigationView) that.findViewById(R.id.nav_view);
TextView user_uid = (TextView) nav_view.getHeaderView(0).findViewById(R.id.user_uid); TextView user_uid = (TextView) nav_view.getHeaderView(0).findViewById(R.id.user_uid);
TextView user_name = (TextView) nav_view.getHeaderView(0).findViewById(R.id.user_name); TextView user_name = (TextView) nav_view.getHeaderView(0).findViewById(R.id.user_name);
Log.d("Activity fragment", "user_name "+user_name);
Log.d("Activity fragment", "user_uid "+user_uid);
Log.d("Activity fragment", "nav_view "+nav_view);
user_name.setText(name); user_name.setText(name);
user_uid.setText(uid); user_uid.setText(uid);*/
that.onNavigationItemSelectedID(R.id.nav_gallery); that.onNavigationItemSelectedID(R.id.nav_gallery);
} }
@@ -115,18 +70,29 @@ public class MainActivity extends AppCompatActivity
that.onNavigationItemSelectedID(R.id.nav_camera); that.onNavigationItemSelectedID(R.id.nav_camera);
} }
}); });
listenerAdded = true; GameService.addGameStateChangeEventListener(NAME, new GameService.OnGameStateChangeEventListener() {
@Override
public void onGameStateChangeEvent(int previous, int state) {
Log.d("Activity fragment", "onGameStateChange - previous: " + previous + " - state: " + state);
if (state == GameService.States.RUNNING || state == GameService.States.ONHOLD_LOADING || state == GameService.States.ONHOLD_RESULT)
that.onNavigationItemSelectedID(R.id.nav_manage);
else if (previous == GameService.States.ONHOLD_RESULT && state == GameService.States.END) {
that.onNavigationItemSelectedID(R.id.nav_slideshow);
} else if (state == GameService.States.PAUSED || state == GameService.States.END) {
that.onNavigationItemSelectedID(R.id.nav_gallery);
} }
} }
});
}
@Override @Override
public void onBackPressed() { public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); /*DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) { if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START); drawer.closeDrawer(GravityCompat.START);
} else { } else {
super.onBackPressed(); super.onBackPressed();
} }*/
} }
@Override @Override
@@ -156,8 +122,7 @@ public class MainActivity extends AppCompatActivity
return this.onNavigationItemSelectedID(item.getItemId()); return this.onNavigationItemSelectedID(item.getItemId());
} }
public boolean onNavigationItemSelectedID(int item) { private boolean onNavigationItemSelectedID(int item) {
Log.d("Activity fragment", "itemselect"+item);
// Handle navigation view item clicks here. // Handle navigation view item clicks here.
try { try {
boolean isLoggedIn = LoginService.isLoggedIn(); boolean isLoggedIn = LoginService.isLoggedIn();
@@ -199,48 +164,10 @@ public class MainActivity extends AppCompatActivity
fragmentTransaction.replace(R.id.relative_content, questionFragment, QuestionFragment.NAME); fragmentTransaction.replace(R.id.relative_content, questionFragment, QuestionFragment.NAME);
fragmentTransaction.commit(); fragmentTransaction.commit();
} }
} else if (item == R.id.nav_share) {
QuestionStartFragment fragment = (QuestionStartFragment) myFragmentManager.findFragmentByTag(QuestionStartFragment.NAME);
if (fragment == null) {
FragmentTransaction fragmentTransaction = myFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.relative_content, questionStartFragment, QuestionStartFragment.NAME);
fragmentTransaction.commit();
}
} }
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); //DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView navigation = (NavigationView) drawer.findViewById(R.id.nav_view); //drawer.closeDrawer(GravityCompat.START);
drawer.closeDrawer(GravityCompat.START);
return true; return true;
} }
@Override
public void onMainFragmentInteraction(Uri uri) {
System.out.print("fragment message");
System.out.print(uri);
}
@Override
public void onLoginFragmentInteraction(Uri uri) {
System.out.print("fragment message login");
System.out.print(uri);
}
@Override
public void onQuestionEndFragmentInteraction(Uri uri) {
System.out.print("fragment message question end");
System.out.print(uri);
}
@Override
public void onQuestionFragmentInteraction(Uri uri) {
System.out.print("fragment message question");
System.out.print(uri);
}
@Override
public void onQuestionStartFragmentInteraction(Uri uri) {
System.out.print("fragment message question");
System.out.print(uri);
}
} }

View File

@@ -1,38 +1,35 @@
package de.hwr_berlin.it14.postgrachelor; package de.hwr_berlin.it14.postgrachelor;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.app.Fragment; import android.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.GridLayout;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import java.util.Iterator;
import java.util.Locale;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotLoggedInException;
import de.hwr_berlin.it14.postgrachelor.Services.GameService;
import de.hwr_berlin.it14.postgrachelor.Services.HighscoreService;
import de.hwr_berlin.it14.postgrachelor.Services.LoginService; import de.hwr_berlin.it14.postgrachelor.Services.LoginService;
import de.hwr_berlin.it14.postgrachelor.Types.Highscores;
import de.hwr_berlin.it14.postgrachelor.Types.HighscoresCategories;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link MainFragment.OnMainFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link MainFragment#newInstance} factory method to * Use the {@link MainFragment#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */
public class MainFragment extends Fragment { public class MainFragment extends Fragment {
public static final String NAME = "MAIN_FRAGMENT"; public static final String NAME = "MAIN_FRAGMENT";
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private boolean listener = false;
private OnMainFragmentInteractionListener mListener;
public MainFragment() { public MainFragment() {
// Required empty public constructor // Required empty public constructor
@@ -42,36 +39,21 @@ public class MainFragment extends Fragment {
* Use this factory method to create a new instance of * Use this factory method to create a new instance of
* this fragment using the provided parameters. * this fragment using the provided parameters.
* *
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment MainFragment. * @return A new instance of fragment MainFragment.
*/ */
// TODO: Rename and change types and number of parameters public static MainFragment newInstance() {
public static MainFragment newInstance(String param1, String param2) {
MainFragment fragment = new MainFragment(); MainFragment fragment = new MainFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@Override @Override
public void onCreate(Bundle savedInstanceState) { public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
this.listener = false;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_main, container, false); final View view = inflater.inflate(R.layout.fragment_main, container, false);
if (!this.listener) {
LoginService.addLoginEventListener(new LoginService.OnLoginEventListener() { LoginService.addLoginEventListener(NAME, new LoginService.OnLoginEventListener() {
@Override @Override
public void onLoginEvent(String name, String uid) { public void onLoginEvent(String name, String uid) {
TextView textView = (TextView) view.findViewById(R.id.fragment_main_status).findViewById(R.id.fragment_user_name); TextView textView = (TextView) view.findViewById(R.id.fragment_main_status).findViewById(R.id.fragment_user_name);
@@ -81,48 +63,107 @@ public class MainFragment extends Fragment {
@Override public void onLogoutEvent(int status, String message) {} @Override public void onLogoutEvent(int status, String message) {}
}); });
this.listener = true; HighscoreService.addHighscoreUpdateEventListener(new HighscoreService.OnHighscoreUpdateEventListener() {
@Override
public void onHighscoreUpdateEvent(Highscores scores) {
Log.d(NAME, "onHighscoreUpdate");
TextView userStatusTextViewScore = (TextView) view.findViewById(R.id.fragment_main_status).findViewById(R.id.fragment_user_score);
ProgressBar userStatusProgressBar = (ProgressBar) view.findViewById(R.id.fragment_main_status).findViewById(R.id.progressBarStatus);
GridLayout gridLayoutCategories = (GridLayout) view.findViewById(R.id.fragment_main_categories);
View categoryView;
GridLayout.LayoutParams param;
gridLayoutCategories.removeAllViews();
if (scores==null) {
userStatusTextViewScore.setText("0");
userStatusProgressBar.setMax(1);
userStatusProgressBar.setProgress(0);
TextView textView;
textView = new TextView(view.getContext());
textView.setText(R.string.no_highscores_available);
textView.setTextColor(ContextCompat.getColor(view.getContext(), R.color.colorPrimaryDark));
gridLayoutCategories.addView(textView);
param = new GridLayout.LayoutParams(GridLayout.spec(GridLayout.UNDEFINED, 1f), GridLayout.spec(GridLayout.UNDEFINED, 1f));
param.width = 0;
textView.setLayoutParams(param);
} else {
Iterator<HighscoresCategories> iterator = scores.getCategoryIterator();
ProgressBar catProgress;
TextView textView;
while(iterator.hasNext()) {
HighscoresCategories category = iterator.next();
categoryView = inflater.inflate(R.layout.fragment_main_category, null);
textView = (TextView) categoryView.findViewById(R.id.textViewCategory);
textView.setText(category.getName());
textView = (TextView) categoryView.findViewById(R.id.textViewScore);
textView.setText(String.format(Locale.getDefault(), "%1$d", category.getScore()));
catProgress = (ProgressBar) categoryView.findViewById(R.id.progressBarCategory);
catProgress.setProgress(category.getPlace());
catProgress.setMax(scores.getAll());
gridLayoutCategories.addView(categoryView);
param = new GridLayout.LayoutParams(GridLayout.spec(GridLayout.UNDEFINED, 1f), GridLayout.spec(GridLayout.UNDEFINED, 1f));
param.width = 0;
categoryView.setLayoutParams(param);
} }
userStatusTextViewScore.setText(String.format(Locale.getDefault(), "%1$d", scores.getScore()));
userStatusProgressBar.setMax(scores.getAll());
userStatusProgressBar.setProgress(scores.getPlace());
}
}
});
GameService.addGameStateChangeEventListener(NAME, new GameService.OnGameStateChangeEventListener() {
@Override
public void onGameStateChangeEvent(int previous, int state) {
Log.d(NAME, "onGameStateChangeEvent");
View userGameBackground = view.findViewById(R.id.fragment_main_game).findViewById(R.id.background);
TextView userGameTextView = (TextView) view.findViewById(R.id.fragment_main_game).findViewById(R.id.title);
ImageButton userStatusImage = (ImageButton) view.findViewById(R.id.fragment_main_game).findViewById(R.id.image_btn);
if (state == GameService.States.END || state == GameService.States.UNINITIALIZED) {
userGameBackground.setBackgroundResource(android.R.color.holo_green_dark);
userGameTextView.setText(R.string.start_test);
userStatusImage.setImageResource(android.R.drawable.ic_media_play);
} else {
userGameBackground.setBackgroundResource(android.R.color.holo_orange_dark);
userGameTextView.setText(R.string.resume_test);
userStatusImage.setImageResource(android.R.drawable.ic_media_pause);
}
}
});
// Inflate the layout for this fragment // Inflate the layout for this fragment
View fragmentMainGameView = view.findViewById(R.id.fragment_main_game);
fragmentMainGameView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
int state = GameService.getState();
Log.d(NAME, "Game click: "+state);
if (state == GameService.States.END || state == GameService.States.UNINITIALIZED) {
GameService.startGame();
} else {
GameService.resumeGame();
}
} catch (NotInstantiatedException | NotLoggedInException e) {
e.printStackTrace();
}
}
});
return view; return view;
} }
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onMainFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnMainFragmentInteractionListener) {
mListener = (OnMainFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnMainFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
interface OnMainFragmentInteractionListener {
// TODO: Update argument type and name
void onMainFragmentInteraction(Uri uri);
}
} }

View File

@@ -1,34 +1,29 @@
package de.hwr_berlin.it14.postgrachelor; package de.hwr_berlin.it14.postgrachelor;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.app.Fragment; import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.Locale;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException;
import de.hwr_berlin.it14.postgrachelor.Services.GameService;
import de.hwr_berlin.it14.postgrachelor.Types.GameScores;
import de.hwr_berlin.it14.postgrachelor.Utils.Conversion;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link QuestionEndFragment.OnQuestionEndFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link QuestionEndFragment#newInstance} factory method to * Use the {@link QuestionEndFragment#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */
public class QuestionEndFragment extends Fragment { public class QuestionEndFragment extends Fragment {
public static final String NAME = "QUESTION_END_FRAGMENT"; public static final String NAME = "QUESTION_END_FRAGMENT";
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnQuestionEndFragmentInteractionListener mListener;
public QuestionEndFragment() { public QuestionEndFragment() {
// Required empty public constructor // Required empty public constructor
@@ -37,73 +32,56 @@ public class QuestionEndFragment extends Fragment {
/** /**
* Use this factory method to create a new instance of * Use this factory method to create a new instance of
* this fragment using the provided parameters. * this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment QuestionEndFragment. * @return A new instance of fragment QuestionEndFragment.
*/ */
// TODO: Rename and change types and number of parameters public static QuestionEndFragment newInstance() {
public static QuestionEndFragment newInstance(String param1, String param2) {
QuestionEndFragment fragment = new QuestionEndFragment(); QuestionEndFragment fragment = new QuestionEndFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_question_end, container, false); final View view = inflater.inflate(R.layout.fragment_question_end, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onQuestionEndFragmentInteraction(uri);
}
}
Button btn = (Button) view.findViewById(R.id.returnBtn);
btn.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onAttach(Context context) { public void onClick(View v) {
super.onAttach(context); try {
if (context instanceof OnQuestionEndFragmentInteractionListener) { GameService.endGame();
mListener = (OnQuestionEndFragmentInteractionListener) context; } catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
});
GameService.addGameEndEventListener(NAME, new GameService.OnGameEndEventListener() {
@Override
public void onGameEndEvent(GameScores scores) {
Log.d(NAME, "onGameEndEvent" + scores);
//scores = new GameScores(100, 43*1000);
//scores = new GameScores(100, 7*60*1000 + 43*1000);
//scores = new GameScores(100, 3*60*60*1000 + 7*60*1000 + 43*1000);
//scores = new GameScores(100, 15*24*60*60*1000 + 3*60*60*1000 + 7*60*1000 + 43*1000);
if (scores != null) {
TextView textView = (TextView) view.findViewById(R.id.textViewScore);
textView.setText(String.format(Locale.getDefault(), "%1$d", scores.getScore()));
textView = (TextView) view.findViewById(R.id.textViewTime);
textView.setText(Conversion.millisToTime(scores.getTime()));
} else { } else {
throw new RuntimeException(context.toString() TextView textView = (TextView) view.findViewById(R.id.textViewScore);
+ " must implement OnQuestionEndFragmentInteractionListener"); textView.setText(R.string.no_score);
}
}
@Override textView = (TextView) view.findViewById(R.id.textViewTime);
public void onDetach() { textView.setText(R.string.no_time);
super.onDetach();
mListener = null;
} }
}
/** });
* This interface must be implemented by activities that contain this return view;
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
interface OnQuestionEndFragmentInteractionListener {
// TODO: Update argument type and name
void onQuestionEndFragmentInteraction(Uri uri);
} }
} }

View File

@@ -1,34 +1,34 @@
package de.hwr_berlin.it14.postgrachelor; package de.hwr_berlin.it14.postgrachelor;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.app.Fragment; import android.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.Locale;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NoCurrentQuestionException;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotLoggedInException;
import de.hwr_berlin.it14.postgrachelor.Services.GameService;
import de.hwr_berlin.it14.postgrachelor.Types.Question;
import de.hwr_berlin.it14.postgrachelor.Types.QuestionResult;
import de.hwr_berlin.it14.postgrachelor.Types.Timings;
import de.hwr_berlin.it14.postgrachelor.Utils.Conversion;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link QuestionFragment.OnQuestionFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link QuestionFragment#newInstance} factory method to * Use the {@link QuestionFragment#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */
public class QuestionFragment extends Fragment { public class QuestionFragment extends Fragment {
public static final String NAME = "QUESTION_FRAGMENT"; public static final String NAME = "QUESTION_FRAGMENT";
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnQuestionFragmentInteractionListener mListener;
public QuestionFragment() { public QuestionFragment() {
// Required empty public constructor // Required empty public constructor
@@ -38,72 +38,118 @@ public class QuestionFragment extends Fragment {
* Use this factory method to create a new instance of * Use this factory method to create a new instance of
* this fragment using the provided parameters. * this fragment using the provided parameters.
* *
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment QuestionFragment. * @return A new instance of fragment QuestionFragment.
*/ */
// TODO: Rename and change types and number of parameters public static QuestionFragment newInstance() {
public static QuestionFragment newInstance(String param1, String param2) {
QuestionFragment fragment = new QuestionFragment(); QuestionFragment fragment = new QuestionFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_question, container, false);
final TextView questionTitleView = (TextView) view.findViewById(R.id.questionTitle);
final TextView questionCategoryView = (TextView) view.findViewById(R.id.questionCategory);
final TextView totalView = (TextView) view.findViewById(R.id.questionTotal);
final TextView timeView = (TextView) view.findViewById(R.id.questionTime);
final TextView scoreView = (TextView) view.findViewById(R.id.questionScore);
final Button[] questionAnswerViews = {
(Button) view.findViewById(R.id.questionAnswer0),
(Button) view.findViewById(R.id.questionAnswer1),
(Button) view.findViewById(R.id.questionAnswer2),
(Button) view.findViewById(R.id.questionAnswer3)
};
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_question, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onQuestionFragmentInteraction(uri);
}
}
for (int i = 0; i < 4; i++) {
questionAnswerViews[i].setTag(i);
questionAnswerViews[i].setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onAttach(Context context) { public void onClick(View v) {
super.onAttach(context); try {
if (context instanceof OnQuestionFragmentInteractionListener) { if (GameService.getState() != GameService.States.ONHOLD_RESULT)
mListener = (OnQuestionFragmentInteractionListener) context; GameService.answer((int) v.getTag());
} catch (NotInstantiatedException | NotLoggedInException | NoCurrentQuestionException e) {
e.printStackTrace();
}
}
});
}
GameService.addResultEventListener(NAME, new GameService.OnResultEventListener() {
@Override
public void onResultEvent(QuestionResult result) {
Log.d(NAME, "onResultEvent - result: " + result);
if (result != null) {
int colorBgClicked = ContextCompat.getColor(getActivity().getApplicationContext(), android.R.color.holo_red_dark);
int colorBg = ContextCompat.getColor(getActivity().getApplicationContext(), android.R.color.holo_green_dark);
int colorText = ContextCompat.getColor(getActivity().getApplicationContext(), android.R.color.black);
int answerID;
try {
answerID = GameService.getAnswer();
} catch (NotInstantiatedException e) {
answerID = 0;
e.printStackTrace();
}
Log.d(NAME, "onResultEvent - answerID: " + answerID);
questionAnswerViews[answerID].setBackgroundColor(colorBgClicked);
questionAnswerViews[result.getCorrectPos()].setBackgroundColor(colorBg);
questionAnswerViews[result.getCorrectPos()].setTextColor(colorText);
totalView.setText(Conversion.intToStr(result.getTotal()));
scoreView.setText(Conversion.intToStr(result.getScore()));
}
}
});
GameService.addNextQuestionEventListener(NAME, new GameService.OnNextQuestionEventListener() {
@Override
public void onNextQuestionEvent(Question question) {
for (int i = 0; i < 4; i++) {
questionAnswerViews[i].setBackgroundColor(
ContextCompat.getColor(view.getContext(), R.color.colorPrimary)
);
questionAnswerViews[i].setTextColor(
ContextCompat.getColor(view.getContext(), android.R.color.white)
);
}
if (question != null) {
questionTitleView.setText(question.getQuestion());
questionCategoryView.setText(view.getContext().getResources().getString(R.string.category, question.getCategory()));
for (int i = 0; i < 4; i++) {
questionAnswerViews[i].setText(question.getAnswers()[i]);
}
} else { } else {
throw new RuntimeException(context.toString() questionTitleView.setText("");
+ " must implement OnFragmentInteractionListener"); questionCategoryView.setText(R.string.no_question_available);
for (int i = 0; i < 4; i++) {
questionAnswerViews[i].setText("");
} }
} }
}
});
GameService.addTickEventListener(NAME, new GameService.OnTickEventListener() {
@Override @Override
public void onDetach() { public void onTickEvent(Timings timings) {
super.onDetach(); if (timings != null) {
mListener = null; timeView.setText(Conversion.millisToTime(timings.getTimeDiff()));
scoreView.setText(String.format(Locale.getDefault(), "%1d", timings.getScore()));
} }
}
/** });
* This interface must be implemented by activities that contain this GameService.addGameStateChangeEventListener(NAME, new GameService.OnGameStateChangeEventListener() {
* fragment to allow an interaction in this fragment to be communicated @Override
* to the activity and potentially other fragments contained in that public void onGameStateChangeEvent(int previous, int state) {
* activity. if (previous == GameService.States.END && state == GameService.States.RUNNING)
* <p> totalView.setText(R.string._0);
* See the Android Training lesson <a href= }
* "http://developer.android.com/training/basics/fragments/communicating.html" });
* >Communicating with Other Fragments</a> for more information. return view;
*/
interface OnQuestionFragmentInteractionListener {
// TODO: Update argument type and name
void onQuestionFragmentInteraction(Uri uri);
} }
} }

View File

@@ -1,109 +0,0 @@
package de.hwr_berlin.it14.postgrachelor;
import android.app.Fragment;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link QuestionStartFragment.OnQuestionStartFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link QuestionStartFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class QuestionStartFragment extends Fragment {
public static final String NAME = "QUESTION_START_FRAGMENT";
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnQuestionStartFragmentInteractionListener mListener;
public QuestionStartFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment QuestionStartFragment.
*/
// TODO: Rename and change types and number of parameters
public static QuestionStartFragment newInstance(String param1, String param2) {
QuestionStartFragment fragment = new QuestionStartFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_question_start, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onQuestionStartFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnQuestionStartFragmentInteractionListener) {
mListener = (OnQuestionStartFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnQuestionStartFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
interface OnQuestionStartFragmentInteractionListener {
// TODO: Update argument type and name
void onQuestionStartFragmentInteraction(Uri uri);
}
}

View File

@@ -0,0 +1,704 @@
package de.hwr_berlin.it14.postgrachelor.Services;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.SharedPreferences;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NoCurrentQuestionException;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotLoggedInException;
import de.hwr_berlin.it14.postgrachelor.Types.GameScores;
import de.hwr_berlin.it14.postgrachelor.Types.Question;
import de.hwr_berlin.it14.postgrachelor.Types.QuestionResult;
import de.hwr_berlin.it14.postgrachelor.Types.Timings;
import de.hwr_berlin.it14.postgrachelor.Utils.JsonRequestPG;
/**
* Created by Sebastian on 27.03.2017.
* Game service controls gameflow
*/
public class GameService {
private static final int GAME_TICK_INTERVAL = 100;
private static final int NEXT_QUESTION_DELAY = 1250;
private static long startTime;
private static long endTime;
private static int answer;
private static Timer timer;
public static final class States {
private States() {}
public static final int UNINITIALIZED = 1;
public static final int END = 2;
public static final int ONHOLD_LOADING = 4;
public static final int ONHOLD_RESULT = 8;
public static final int RUNNING = 16;
public static final int PAUSED = 32;
}
private static final String PREFS_NAME = "PrefsGame";
private static SharedPreferences settings = null;
private static boolean initialized = false;
@SuppressLint("StaticFieldLeak")
private static Activity activity = null;
private static final HashMap<String, OnGameStateChangeEventListener> gameStateChangeEventListeners = new HashMap<>();
private static final HashMap<String, OnNextQuestionEventListener> nextQuestionEventListeners = new HashMap<>();
private static final HashMap<String, OnResultEventListener> resultEventListeners = new HashMap<>();
private static final HashMap<String, OnGameEndEventListener> gameEndEventListeners = new HashMap<>();
private static final HashMap<String, OnTickEventListener> gameTickEventListeners = new HashMap<>();
private static int state = States.END;
private static Question question = null;
private static QuestionResult result = null;
private static GameScores scores = null;
public interface OnGameStateChangeEventListener {
void onGameStateChangeEvent(int previous, int state);
}
public interface OnNextQuestionEventListener {
void onNextQuestionEvent(Question question);
}
public interface OnResultEventListener {
void onResultEvent(QuestionResult result);
}
public interface OnGameEndEventListener {
void onGameEndEvent(GameScores scores);
}
public interface OnTickEventListener {
void onTickEvent(Timings timings);
}
private GameService() {}
public static void initialize(Activity activity) {
GameService.activity = activity;
GameService.settings = activity.getSharedPreferences(GameService.PREFS_NAME, 0);
GameService.initialized = true;
emitNextQuestionEvent();
emitGameEndEvent();
emitResultEvent();
emitGameStateChangeEvent();
}
public static void addGameStateChangeEventListener(String key, OnGameStateChangeEventListener onGameStateChangeEventListener) {
gameStateChangeEventListeners.put(key, onGameStateChangeEventListener);
if (GameService.initialized)
onGameStateChangeEventListener.onGameStateChangeEvent(-2, GameService.getStateSave());
}
private static void emitGameStateChangeEvent() {
for (OnGameStateChangeEventListener listener: gameStateChangeEventListeners.values()) {
listener.onGameStateChangeEvent(-1, GameService.getStateSave());
}
}
private static void emitGameStateChangeEvent(int previousState) {
for (OnGameStateChangeEventListener listener: gameStateChangeEventListeners.values()) {
listener.onGameStateChangeEvent(previousState, GameService.getStateSave());
}
}
public static void addNextQuestionEventListener(String key, OnNextQuestionEventListener onNextQuestionEventListener) {
Log.d("GameService Fragment", "addNextQuestionEventListener");
nextQuestionEventListeners.put(key, onNextQuestionEventListener);
if (GameService.initialized)
onNextQuestionEventListener.onNextQuestionEvent(GameService.getQuestionSave());
}
private static void emitNextQuestionEvent() {
for (OnNextQuestionEventListener listener: nextQuestionEventListeners.values()) {
listener.onNextQuestionEvent(GameService.getQuestionSave());
}
}
public static void addResultEventListener(String key, OnResultEventListener onResultEventListener) {
resultEventListeners.put(key, onResultEventListener);
if (GameService.initialized)
onResultEventListener.onResultEvent(GameService.getResultSave());
}
private static void emitResultEvent() {
for (OnResultEventListener listener: resultEventListeners.values()) {
listener.onResultEvent(GameService.getResultSave());
}
}
public static void addGameEndEventListener(String key, OnGameEndEventListener onGameEndEventListener) {
gameEndEventListeners.put(key, onGameEndEventListener);
if (GameService.initialized)
onGameEndEventListener.onGameEndEvent(GameService.getScoresSave());
}
private static void emitGameEndEvent() {
for (OnGameEndEventListener listener: gameEndEventListeners.values()) {
listener.onGameEndEvent(GameService.getScoresSave());
}
}
public static void addTickEventListener(String key, OnTickEventListener onTickEventListener) {
gameTickEventListeners.put(key, onTickEventListener);
if (GameService.initialized)
onTickEventListener.onTickEvent(GameService.getTimingsSave());
}
private static Timings getTimingsSave() {
try {
return GameService.getTimings();
} catch (NotInstantiatedException e) {
e.printStackTrace();
return null;
}
}
private static Timings getTimings() throws NotInstantiatedException {
long timeDiff = GameService.getStartTime();
timeDiff = System.currentTimeMillis()-timeDiff;
int score;
if (timeDiff <= 2000)
score = 1000;
else
score = Math.max((int) Math.floor(1025 - 5*Math.sqrt(2*timeDiff-3975)), 10);
return new Timings(timeDiff, score);
}
private static void emitTickEvent() {
for (OnTickEventListener listener: gameTickEventListeners.values()) {
listener.onTickEvent(GameService.getTimingsSave());
}
}
private static void startTimer() {
if (GameService.timer==null)
GameService.timer = new Timer();
GameService.timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
GameService.activity.runOnUiThread(new Runnable() {
@Override
public void run() {
emitTickEvent();
}
});
}
}, 0, GameService.GAME_TICK_INTERVAL);
}
private static void stopTimer() {
if (GameService.timer != null)
GameService.timer.cancel();
GameService.timer = null;
}
private static GameScores getScores() throws NotInstantiatedException {
if (GameService.scores == null) {
if (!GameService.initialized)
throw new NotInstantiatedException();
GameScores scores;
if (GameService.settings.contains("gameScore")) {
scores = new GameScores(
GameService.settings.getInt("gameScore", 0),
GameService.settings.getInt("gameTime", 0)
);
} else {
scores = null;
}
GameService.scores = scores;
}
return GameService.scores;
}
private static GameScores getScoresSave() {
try {
return GameService.getScores();
} catch (NotInstantiatedException e) {
e.printStackTrace();
return null;
}
}
public static int getState() throws NotInstantiatedException {
if (GameService.state == GameService.States.UNINITIALIZED) {
if (!GameService.initialized)
throw new NotInstantiatedException();
int state = GameService.settings.getInt("gameState", GameService.States.UNINITIALIZED);
if (state == GameService.States.UNINITIALIZED) {
state = GameService.States.END;
SharedPreferences.Editor editor = GameService.settings.edit();
editor.putInt("gameState", state);
editor.apply();
}
GameService.state = state;
}
return GameService.state;
}
private static int getStateSave() {
try {
return GameService.getState();
} catch (NotInstantiatedException e) {
e.printStackTrace();
return States.UNINITIALIZED;
}
}
private static Question getQuestion() throws NotInstantiatedException {
if (GameService.question == null) {
if (!GameService.initialized)
throw new NotInstantiatedException();
Question question;
if (GameService.settings.contains("question")) {
question = new Question(
GameService.settings.getString("questionCategory", ""),
GameService.settings.getInt("questionCategoryID", 0),
GameService.settings.getString("question", ""),
new String [] {
GameService.settings.getString("answer0", ""),
GameService.settings.getString("answer1", ""),
GameService.settings.getString("answer2", ""),
GameService.settings.getString("answer3", "")
}
);
} else {
question = null;
}
GameService.question = question;
}
return GameService.question;
}
private static Question getQuestionSave() {
try {
return GameService.getQuestion();
} catch (NotInstantiatedException e) {
e.printStackTrace();
return null;
}
}
private static QuestionResult getResult() throws NotInstantiatedException {
if (GameService.result == null) {
if (!GameService.initialized)
throw new NotInstantiatedException();
QuestionResult result;
if (GameService.settings.contains("resultCorrect")) {
result = new QuestionResult(
GameService.settings.getBoolean("resultCorrect", true),
GameService.settings.getInt("resultScore", 0),
GameService.settings.getInt("resultPos", 0),
GameService.settings.getInt("resultTotal", 0)
);
} else {
result = null;
}
GameService.result = result;
}
return GameService.result;
}
private static QuestionResult getResultSave() {
try {
return GameService.getResult();
} catch (NotInstantiatedException e) {
e.printStackTrace();
return null;
}
}
private static long getStartTime() throws NotInstantiatedException {
if (GameService.startTime == 0) {
if (!GameService.initialized)
throw new NotInstantiatedException();
GameService.startTime = GameService.settings.getLong("startTime", 0);
}
return GameService.startTime;
}
private static long getEndTime() throws NotInstantiatedException {
if (GameService.endTime == 0) {
if (!GameService.initialized)
throw new NotInstantiatedException();
GameService.endTime = GameService.settings.getLong("endTime", 0);
}
return GameService.endTime;
}
private static int getAnswer(int id) throws NotInstantiatedException {
if (GameService.answer == 0) {
if (!GameService.initialized)
throw new NotInstantiatedException();
GameService.answer = GameService.settings.getInt("answer", id);
}
return GameService.answer;
}
public static int getAnswer() throws NotInstantiatedException {
return GameService.getAnswer(0);
}
public static void pauseGame() throws NotInstantiatedException {
GameService.setState(States.PAUSED);
}
public static void resumeGame() throws NotInstantiatedException {
GameService.setState(States.RUNNING);
}
public static void endGame() throws NotInstantiatedException {
GameService.setState(States.END);
GameService.unsetEndTime();
GameService.unsetStartTime();
GameService.unsetScores();
}
public static void answer(int id) throws NotInstantiatedException, NotLoggedInException, NoCurrentQuestionException {
if (!GameService.initialized)
throw new NotInstantiatedException();
final int state = GameService.getState();
long time;
if (state == States.ONHOLD_LOADING) {
long end = GameService.getEndTime();
long start = GameService.getStartTime();
time = end - start;
id = GameService.getAnswer(id);
} else if (state == States.RUNNING) {
long end = System.currentTimeMillis();
long start = GameService.getStartTime();
GameService.setEndTime(end);
GameService.setState(States.ONHOLD_LOADING);
time = end - start;
GameService.setAnswer(id);
} else {
throw new NoCurrentQuestionException();
}
HashMap<String, String> params = new HashMap<>();
String uid;
if (LoginService.isLoggedIn())
uid = LoginService.getLoginUID();
else
throw new NotLoggedInException();
params.put("answer", Integer.toString(id));
params.put("uid", uid);
params.put("time", Long.toString(time));
Log.d("GameServiceFragment", "answer/processFinish - before");
JsonRequestPG requester = new JsonRequestPG("answer.php", params, GameService.activity, new JsonRequestPG.AsyncResponse() {
@Override
public void processFinish(final JSONObject data) {
Log.d("GameServiceFragment", "answer/processFinish - " + data.toString());
JSONObject data_result = data.optJSONObject("results");
QuestionResult result = new QuestionResult(
data_result.optBoolean("correct", false),
data_result.optInt("score", 0),
data_result.optInt("correctPos", 0),
data_result.optInt("total", 0)
);
GameService.setStateSave(States.ONHOLD_RESULT);
GameService.setResultSave(result);
new android.os.Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (data.has("next")) {
JSONObject data_next = data.optJSONObject("next");
GameService.setQuestionSave(GameService.parseQuestion(data_next));
GameService.setStartTimeSave(System.currentTimeMillis());
GameService.setStateSave(States.RUNNING);
} else {
JSONObject data_end = data.optJSONObject("end");
GameService.setScoresSave(GameService.parseScores(data_end));
GameService.setStateSave(States.END);
GameService.unsetStartTimeSave();
GameService.unsetEndTimeSave();
}
}
}, GameService.NEXT_QUESTION_DELAY);
}
@Override
public void processError(int status, String message) {
Log.d("GameServiceFragment", "answer/processError "+status+" "+message);
if (status==13104)
try {
GameService.endGame();
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
});
requester.execute();
}
public static void startGame() throws NotInstantiatedException, NotLoggedInException {
if (!GameService.initialized)
throw new NotInstantiatedException();
HashMap<String, String> params = new HashMap<>();
String uid;
if (LoginService.isLoggedIn())
uid = LoginService.getLoginUID();
else
throw new NotLoggedInException();
params.put("uid", uid);
JsonRequestPG requester = new JsonRequestPG("start.php", params, GameService.activity, new JsonRequestPG.AsyncResponse() {
@Override
public void processFinish(JSONObject data) {
JSONObject data_next = data.optJSONObject("next");
if (data_next != null) {
GameService.setStateSave(States.RUNNING);
GameService.setStartTimeSave(System.currentTimeMillis());
GameService.unsetEndTimeSave();
GameService.unsetScoresSave();
GameService.setQuestionSave(GameService.parseQuestion(data_next));
} else {
GameService.setStateSave(States.END);
}
}
@Override
public void processError(int status, String message) {
GameService.setStateSave(States.END);
}
});
requester.execute();
}
private static void setQuestion(Question question) throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.question = question;
SharedPreferences.Editor editor = GameService.settings.edit();
if (question != null) {
editor.putString("questionCategory", question.getCategory());
editor.putInt("questionCategoryID", question.getCategoryID());
editor.putString("question", question.getQuestion());
String[] answers = question.getAnswers();
editor.putString("answer0", answers[0]);
editor.putString("answer1", answers[1]);
editor.putString("answer2", answers[2]);
editor.putString("answer3", answers[3]);
} else {
editor.remove("questionCategory");
editor.remove("questionCategoryID");
editor.remove("question");
editor.remove("answer0");
editor.remove("answer1");
editor.remove("answer2");
editor.remove("answer3");
}
editor.apply();
GameService.emitNextQuestionEvent();
}
private static void setQuestionSave(Question question) {
try {
GameService.setQuestion(question);
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void setState(int state) throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
int previous = GameService.getState();
GameService.state = state;
SharedPreferences.Editor editor = GameService.settings.edit();
if (state==States.UNINITIALIZED)
editor.putInt("gameState", state);
else
editor.remove("gameState");
editor.apply();
if (GameService.state != States.RUNNING)
GameService.stopTimer();
GameService.emitGameStateChangeEvent(previous);
if (GameService.state == States.RUNNING)
GameService.startTimer();
}
private static void setStateSave(int state) {
try {
GameService.setState(state);
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void setResult(QuestionResult result) throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.result = result;
SharedPreferences.Editor editor = GameService.settings.edit();
if (result != null) {
editor.putInt("resultScore", result.getScore());
editor.putBoolean("resultCorrect", result.isCorrect());
editor.putInt("resultPos", result.getCorrectPos());
editor.putInt("resultTotal", result.getTotal());
} else {
editor.remove("resultScore");
editor.remove("resultCorrect");
editor.remove("resultPos");
editor.remove("resultTotal");
}
editor.apply();
GameService.emitResultEvent();
}
private static void setResultSave(QuestionResult result) {
try {
GameService.setResult(result);
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void setScores(GameScores gameScores) throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.scores = gameScores;
SharedPreferences.Editor editor = GameService.settings.edit();
if (gameScores != null) {
editor.putInt("gameScore", gameScores.getScore());
editor.putInt("gameTime", gameScores.getTime());
} else {
editor.remove("gameScore");
editor.remove("gameTime");
}
editor.apply();
GameService.emitGameEndEvent();
}
private static void setScoresSave(GameScores gameScores) {
try {
GameService.setScores(gameScores);
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void unsetScores() throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.scores = null;
SharedPreferences.Editor editor = GameService.settings.edit();
editor.remove("gameScore");
editor.remove("gameTime");
editor.apply();
}
private static void unsetScoresSave() {
try {
GameService.unsetScores();
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void setStartTime(long startTime) throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.startTime = startTime;
SharedPreferences.Editor editor = GameService.settings.edit();
editor.putLong("startTime", startTime);
editor.apply();
}
private static void setStartTimeSave(long startTime) {
try {
GameService.setStartTime(startTime);
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void setEndTime(long endTime) throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.endTime = endTime;
SharedPreferences.Editor editor = GameService.settings.edit();
editor.putLong("endTime", endTime);
editor.apply();
}
private static void unsetStartTime() throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.startTime = 0;
SharedPreferences.Editor editor = GameService.settings.edit();
editor.remove("startTime");
editor.apply();
}
private static void unsetStartTimeSave() {
try {
GameService.unsetStartTime();
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void unsetEndTime() throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.endTime = 0;
SharedPreferences.Editor editor = GameService.settings.edit();
editor.remove("endTime");
editor.apply();
}
private static void unsetEndTimeSave() {
try {
GameService.unsetEndTime();
} catch (NotInstantiatedException e) {
e.printStackTrace();
}
}
private static void setAnswer(int id) throws NotInstantiatedException {
if (!initialized)
throw new NotInstantiatedException();
GameService.answer = id;
SharedPreferences.Editor editor = GameService.settings.edit();
editor.putInt("answer", id);
editor.apply();
}
private static Question parseQuestion(JSONObject data_next) {
JSONArray data_next_arr = data_next.optJSONArray("answers");
return new Question(
data_next.optString("categoryName", ""),
data_next.optInt("categoryID", 0),
data_next.optString("question", ""),
new String[]{
data_next_arr.optString(0, ""),
data_next_arr.optString(1, ""),
data_next_arr.optString(2, ""),
data_next_arr.optString(3, "")
}
);
}
private static GameScores parseScores(JSONObject data_end) {
return new GameScores(
data_end.optInt("score", 0),
data_end.optInt("time", 0)
);
}
}

View File

@@ -0,0 +1,137 @@
package de.hwr_berlin.it14.postgrachelor.Services;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException;
import de.hwr_berlin.it14.postgrachelor.Types.GameScores;
import de.hwr_berlin.it14.postgrachelor.Types.Highscores;
import de.hwr_berlin.it14.postgrachelor.Utils.JsonRequestPG;
/**
* Created by sebastian on 25.03.17.
* Login service
*/
public class HighscoreService {
private static final String NAME = "HighscoreService";
//private static final String PREFS_NAME = "PrefsHighscore";
//private static SharedPreferences settings = null;
private static Highscores latestScores = null;
private static boolean instantiated = false;
@SuppressLint("StaticFieldLeak")
private static Activity activity = null;
private static final ArrayList<OnHighscoreUpdateEventListener> highscoreUpdateEventListeners = new ArrayList<>();
public interface OnHighscoreUpdateEventListener {
void onHighscoreUpdateEvent(Highscores scores);
}
public static void addHighscoreUpdateEventListener(OnHighscoreUpdateEventListener onLoginEventListener) {
highscoreUpdateEventListeners.add(onLoginEventListener);
onLoginEventListener.onHighscoreUpdateEvent(HighscoreService.latestScores);
}
private static void emitHighscoreUpdateEvent() {
for (OnHighscoreUpdateEventListener listener: highscoreUpdateEventListeners) {
listener.onHighscoreUpdateEvent(latestScores);
}
}
public static void instantiate(Activity activity) {
//settings = activity.getSharedPreferences(PREFS_NAME, 0);
HighscoreService.activity = activity;
instantiated = true;
LoginService.addLoginEventListener(NAME, new LoginService.OnLoginEventListener() {
@Override
public void onLoginEvent(String name, String uid) {
try {
HighscoreService.updateHighscores();
} catch (NotInstantiatedException e) {
e.printStackTrace();
HighscoreService.setLatestScores(null);
}
}
@Override
public void onLogoutEvent(int status, String message) {
HighscoreService.setLatestScores(null);
}
});
GameService.addGameEndEventListener(NAME, new GameService.OnGameEndEventListener() {
@Override
public void onGameEndEvent(GameScores scores) {
try {
HighscoreService.updateHighscores();
} catch (NotInstantiatedException e) {
e.printStackTrace();
HighscoreService.setLatestScores(null);
}
}
});
}
public static boolean available() {
return (HighscoreService.latestScores != null);
}
public static Highscores getLatestScores() {
return HighscoreService.latestScores;
}
private static void setLatestScores(Highscores scores) {
latestScores = scores;
emitHighscoreUpdateEvent();
}
private static void updateHighscores() throws NotInstantiatedException {
if (!instantiated)
throw new NotInstantiatedException();
JsonRequestPG requester = new JsonRequestPG("highscores.php", null, activity, new JsonRequestPG.AsyncResponse() {
@Override
public void processFinish(JSONObject output) {
Log.d("Activity fragment", "output");
Log.d("Activity fragment", output.toString());
// never reached if not instantiated
Highscores result = new Highscores(
output.optInt("score", 0),
output.optInt("place", 0),
output.optInt("all", 1)
);
JSONArray array = output.optJSONArray("categories");
if (array != null) {
int max = array.length();
for (int i = 0; i < max; i++) {
try {
JSONObject category = array.getJSONObject(i);
result.addCategory(
category.optInt("id", 0),
category.optString("name", ""),
category.optInt("score", 0),
category.optInt("place", 0)
);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
setLatestScores(result);
}
@Override
public void processError(int status, String message) {
setLatestScores(null);
}
});
requester.execute();
}
}

View File

@@ -1,141 +0,0 @@
package de.hwr_berlin.it14.postgrachelor.Services;
import android.app.Activity;
import android.app.ProgressDialog;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.StringTokenizer;
import static android.content.ContentValues.TAG;
abstract class JsonRequest extends AsyncTask<Void, Void, JSONObject> {
private final String connectionURL;
protected final String path;
private final HashMap<String, String> params;
protected final Activity activity;
private ProgressDialog pDialog;
JsonRequest(String path, HashMap<String, String> params, Activity activity) {
this.connectionURL = getConnectionURL();
this.path = path;
this.params = params;
this.activity = activity;
Log.d("fragment, JSONRequest", connectionURL+path);
}
protected abstract String getConnectionURL();
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.d("fragment, JSONRequest", "onPre1");
// Showing progress dialog
pDialog = new ProgressDialog(this.activity);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
@Override
protected JSONObject doInBackground(Void... arg0) {
URL url = null;
String jsonText = "";
JSONObject jsonObj = null;
try {
url = new URL(parseURL(this.connectionURL+this.path, this.params));
} catch (MalformedURLException e) {
e.printStackTrace();
}
HttpURLConnection urlConnection = null;
if (url == null)
return new JSONObject();
try {
urlConnection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
if (urlConnection == null)
return new JSONObject();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\\A");
jsonText = s.hasNext() ? s.next() : "";
} catch (IOException e) {
e.printStackTrace();
} finally {
urlConnection.disconnect();
}
//jsonText = "{\"meta\":{\"status\": 0, \"message\": \"Success\"}, \"data\": {}}";
// register
// jsonText = "{\"meta\":{\"status\": 0, \"message\": \"Success\"}, \"data\": {}}";
if (!jsonText.equals("")) {
try {
jsonObj = new JSONObject(jsonText);
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity.getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity.getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return jsonObj;
}
@Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
if (pDialog.isShowing())
pDialog.dismiss();
}
private String parseURL(String url, Map<String, String> params)
{
Uri.Builder builder = Uri.parse(url).buildUpon();
if (params != null) {
for (String key : params.keySet()) {
builder.appendQueryParameter(key, params.get(key));
}
}
return builder.build().toString();
}
}

View File

@@ -1,68 +0,0 @@
package de.hwr_berlin.it14.postgrachelor.Services;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import org.json.JSONObject;
import java.util.HashMap;
/**
* Created by sebastian on 19.03.17.
* Implementation of JsonRequest
*/
class JsonRequestPG extends JsonRequest {
private final AsyncResponse delegate;
interface AsyncResponse {
void processFinish(JSONObject data);
void processError(int status, String message);
}
JsonRequestPG(String path, HashMap<String, String> params, Activity activity, AsyncResponse delegate) {
super(path, params, activity);
this.delegate = delegate;
}
@Override
protected String getConnectionURL() {
return "http://leander.sebse.de/";
}
@Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
if (result == null) {
delegate.processError(-1, "Internal error occurred!");
return;
}
JSONObject meta = result.optJSONObject("meta");
if (meta==null) {
delegate.processError(-2, "Invalid JSON: Meta tag not found!");
return;
}
int status = meta.optInt("status", -3);
String message = meta.optString("message", "");
if (status != 0) {
new AlertDialog.Builder(this.activity)
.setTitle("Error "+status)
.setMessage(message)
.setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
delegate.processError(status, message);
return;
}
JSONObject data = result.optJSONObject("data");
delegate.processFinish(data);
}
}

View File

@@ -7,10 +7,10 @@ import android.util.Log;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException; import de.hwr_berlin.it14.postgrachelor.Exceptions.NotInstantiatedException;
import de.hwr_berlin.it14.postgrachelor.Utils.JsonRequestPG;
/** /**
* Created by sebastian on 25.03.17. * Created by sebastian on 25.03.17.
@@ -23,15 +23,15 @@ public class LoginService {
private static boolean instantiated = false; private static boolean instantiated = false;
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
private static Activity activity = null; private static Activity activity = null;
private static ArrayList<OnLoginEventListener> loginEventListeners = new ArrayList<>(); private static final HashMap<String, OnLoginEventListener> loginEventListeners = new HashMap<>();
public interface OnLoginEventListener { public interface OnLoginEventListener {
void onLoginEvent(String name, String uid); void onLoginEvent(String name, String uid);
void onLogoutEvent(int status, String message); void onLogoutEvent(int status, String message);
} }
public static void addLoginEventListener(OnLoginEventListener onLoginEventListener) { public static void addLoginEventListener(String key, OnLoginEventListener onLoginEventListener) {
loginEventListeners.add(onLoginEventListener); loginEventListeners.put(key, onLoginEventListener);
if (isLoggedInSave()) { if (isLoggedInSave()) {
try { try {
onLoginEventListener.onLoginEvent(getLoginName(), getLoginUID()); onLoginEventListener.onLoginEvent(getLoginName(), getLoginUID());
@@ -44,13 +44,13 @@ public class LoginService {
} }
private static void emitLoginEvent(String name, String uid) { private static void emitLoginEvent(String name, String uid) {
for (OnLoginEventListener listener: loginEventListeners) { for (OnLoginEventListener listener: loginEventListeners.values()) {
listener.onLoginEvent(name, uid); listener.onLoginEvent(name, uid);
} }
} }
private static void emitLogoutEvent(int status, String message) { private static void emitLogoutEvent(int status, String message) {
for (OnLoginEventListener listener: loginEventListeners) { for (OnLoginEventListener listener: loginEventListeners.values()) {
listener.onLogoutEvent(status, message); listener.onLogoutEvent(status, message);
} }
} }
@@ -94,7 +94,7 @@ public class LoginService {
return settings.getString("loginName", ""); return settings.getString("loginName", "");
} }
private static String getLoginUID() throws NotInstantiatedException { static String getLoginUID() throws NotInstantiatedException {
if (!LoginService.isLoggedIn()) if (!LoginService.isLoggedIn())
return ""; return "";
return settings.getString("loginUID", ""); return settings.getString("loginUID", "");

View File

@@ -0,0 +1,25 @@
package de.hwr_berlin.it14.postgrachelor.Types;
/**
* Created by Sebastian on 30.03.2017.
* Games scores on game end
*/
public class GameScores {
private final int score;
private final int time;
public GameScores(int score, int time) {
this.score = score;
this.time = time;
}
public int getScore() {
return score;
}
public int getTime() {
return time;
}
}

View File

@@ -0,0 +1,43 @@
package de.hwr_berlin.it14.postgrachelor.Types;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Created by Sebastian on 27.03.2017.
* Contains all highscores
*/
public class Highscores {
private int score = 0;
private int place = 0;
private int all = 0;
private final ArrayList<HighscoresCategories> categories;
public Highscores(int score, int place, int all) {
this.score = score;
this.place = place;
this.all = all;
this.categories = new ArrayList<>();
}
public void addCategory(int id, String name, int score, int place) {
this.categories.add(new HighscoresCategories(id, name, score, place));
}
public int getScore() {
return this.score;
}
public int getPlace() {
return this.place;
}
public int getAll() {
return this.all;
}
public Iterator<HighscoresCategories> getCategoryIterator() {
return this.categories.iterator();
}
}

View File

@@ -0,0 +1,36 @@
package de.hwr_berlin.it14.postgrachelor.Types;
/**
* Created by Sebastian on 27.03.2017.
* Statistics of a single category
*/
public class HighscoresCategories {
private final int id;
private final String name;
private final int score;
private final int place;
HighscoresCategories(int id, String name, int score, int place) {
this.id = id;
this.name = name;
this.score = score;
this.place = place;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public int getScore() {
return this.score;
}
public int getPlace() {
return this.place;
}
}

View File

@@ -0,0 +1,36 @@
package de.hwr_berlin.it14.postgrachelor.Types;
/**
* Created by Sebastian on 30.03.2017.
* Contains all data related to a question (question, answer, category)
*/
public class Question {
private final String category;
private final int categoryID;
private final String question;
private final String[] answers;
public Question(String category, int categoryID, String question, String[] answers) {
this.category = category;
this.categoryID = categoryID;
this.question = question;
this.answers = answers;
}
public String getCategory() {
return category;
}
public int getCategoryID() {
return categoryID;
}
public String getQuestion() {
return question;
}
public String[] getAnswers() {
return answers;
}
}

View File

@@ -0,0 +1,36 @@
package de.hwr_berlin.it14.postgrachelor.Types;
/**
* Created by Sebastian on 30.03.2017.
* Contains statistics of answering the last question
*/
public class QuestionResult {
private final int score;
private final int correctPos;
private final int total;
private final boolean correct;
public QuestionResult(boolean correct, int score, int correctPos, int total) {
this.correct = correct;
this.score = score;
this.correctPos = correctPos;
this.total = total;
}
public int getScore() {
return score;
}
public boolean isCorrect() {
return correct;
}
public int getCorrectPos() {
return correctPos;
}
public int getTotal() {
return total;
}
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadiusRatio="7" android:innerRadiusRatio="6"
android:shape="ring" android:shape="ring"
android:thickness="10dp" > android:thickness="10dp" >
<solid android:color="@color/colorPrimaryDark" /> <solid android:color="@color/colorPrimaryDark" />

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout" android:id="@+id/drawer_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -13,13 +12,13 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<android.support.design.widget.NavigationView <!--<android.support.design.widget.NavigationView
android:id="@+id/nav_view" android:id="@+id/nav_view"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="start" android:layout_gravity="start"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main" app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" /> app:menu="@menu/activity_main_drawer" />-->
</android.support.v4.widget.DrawerLayout> </android.support.v4.widget.DrawerLayout>

View File

@@ -12,6 +12,11 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/fragment_main_game"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/fragment_main_game"/>
<include layout="@layout/fragment_main_status" <include layout="@layout/fragment_main_status"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -20,7 +25,7 @@
<android.support.v7.widget.GridLayout <android.support.v7.widget.GridLayout
xmlns:grid="http://schemas.android.com/apk/res-auto" xmlns:grid="http://schemas.android.com/apk/res-auto"
android:id="@+id/choice_grid" android:id="@+id/fragment_main_categories"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="4dp" android:padding="4dp"
@@ -29,36 +34,6 @@
grid:columnCount="2" grid:columnCount="2"
grid:rowOrderPreserved="false" grid:rowOrderPreserved="false"
grid:useDefaultMargins="true"> grid:useDefaultMargins="true">
<include layout="@layout/fragment_main_category"
android:layout_width="0dp"
android:layout_height="wrap_content"
grid:layout_columnWeight="1"
grid:layout_gravity="fill"
/>
<include layout="@layout/fragment_main_category"
android:layout_width="0dp"
android:layout_height="wrap_content"
grid:layout_columnWeight="1"
grid:layout_gravity="fill"
/>
<include layout="@layout/fragment_main_category"
android:layout_width="0dp"
android:layout_height="wrap_content"
grid:layout_columnWeight="1"
grid:layout_gravity="fill"
/>
<include layout="@layout/fragment_main_category"
android:layout_width="0dp"
android:layout_height="wrap_content"
grid:layout_columnWeight="1"
grid:layout_gravity="fill"
/>
</android.support.v7.widget.GridLayout> </android.support.v7.widget.GridLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -6,24 +6,32 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:gravity="start" android:gravity="start"
android:background="#FF33B5E6" > android:background="#FF33B5E6"
android:padding="5dp"
>
<TextView <TextView
android:id="@+id/textViewCategory"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="100dp" android:layout_height="100dp"
android:text="@string/hello_blank_fragment" /> android:text="@string/hello_blank_fragment" />
<ProgressBar <ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal" style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/progressBarCategory"
android:progressDrawable="@drawable/circular_progress_drawable_red" android:progressDrawable="@drawable/circular_progress_drawable_red"
android:rotation="-90"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:paddingTop="10dp" android:paddingEnd="10dp"
android:minHeight="70dp" android:minHeight="100dp"
android:maxWidth="70dp" android:maxWidth="100dp"
android:indeterminate="false" android:indeterminate="false"
android:max="100" android:max="900"
android:progress="75"/> android:progress="300"
android:paddingRight="10dp"
android:paddingLeft="10dp"/>
<TextView <TextView
android:id="@+id/textViewScore"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:showIn="@layout/fragment_main"
android:padding="5dp">
<View
android:id="@+id/background"
android:background="@android:color/holo_orange_dark"
android:layout_width="match_parent"
android:layout_height="90dp"
android:max="100"
android:minHeight="90dp"
android:maxHeight="90dp"
android:progress="20"/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Title"
android:textColor="@android:color/white"
android:padding="10dp"
android:paddingBottom="0dp"
android:layout_centerVertical="true"
android:text="@string/start_test"
tools:ignore="RelativeOverlap" />
<ImageButton
android:contentDescription="@string/play_a_game"
android:id="@+id/image_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_media_play"
android:background="@android:color/transparent"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:paddingEnd="50dp"
android:paddingStart="50dp"
android:layout_alignParentRight="true"
android:paddingRight="50dp"
android:paddingLeft="50dp" />
</RelativeLayout>

View File

@@ -8,7 +8,7 @@
android:padding="5dp"> android:padding="5dp">
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBarStatus"
style="@style/Widget.AppCompat.ProgressBar.Horizontal" style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:progressDrawable="@drawable/horizontal_progress_drawable_red" android:progressDrawable="@drawable/horizontal_progress_drawable_red"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -29,6 +29,7 @@
android:text="@string/hello_blank_fragment" /> android:text="@string/hello_blank_fragment" />
<TextView <TextView
android:id="@+id/fragment_user_score"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end" android:gravity="end"

View File

@@ -9,9 +9,49 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_margin="20dp" android:layout_margin="20dp"
android:id="@+id/questionCategory"
android:text="@string/android_studio_email" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="20dp"
android:paddingTop="20sp"
android:textAppearance="@style/TextAppearance.AppCompat.Title" android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:id="@+id/questionTitle"
android:text="@string/welcome_text" /> android:text="@string/welcome_text" />
<TextView
android:id="@+id/questionTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/_02_15"
android:layout_marginBottom="330sp"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:layout_alignParentBottom="true"
/>
<TextView
android:id="@+id/questionScore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/_1337"
android:layout_marginBottom="330sp"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
/>
<TextView
android:id="@+id/questionTotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="330sp"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
tools:ignore="RelativeOverlap"
android:layout_alignParentRight="true" />
<Button <Button
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -21,6 +61,7 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:id="@+id/questionAnswer0"
android:text="@string/welcome_text"/> android:text="@string/welcome_text"/>
<Button <Button
@@ -32,6 +73,7 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:id="@+id/questionAnswer1"
android:text="@string/welcome_text"/> android:text="@string/welcome_text"/>
<Button <Button
@@ -43,6 +85,7 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:id="@+id/questionAnswer2"
android:text="@string/welcome_text"/> android:text="@string/welcome_text"/>
<Button <Button
@@ -56,6 +99,7 @@
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:id="@+id/questionAnswer3"
android:text="@string/welcome_text"/> android:text="@string/welcome_text"/>
</RelativeLayout> </RelativeLayout>

View File

@@ -14,16 +14,28 @@
android:textSize="40sp" android:textSize="40sp"
android:text="@string/test_completed" /> android:text="@string/test_completed" />
<TextView <TextView
android:id="@+id/textViewScore"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:paddingBottom="40dp"
android:textSize="80sp" android:textSize="80sp"
android:text="@string/_1337" android:text="@string/_1337"
android:maxLines="1" android:maxLines="1"
android:textColor="@color/colorPrimaryDark" android:textColor="@color/colorPrimaryDark"
android:textStyle="bold"/> android:textStyle="bold"/>
<TextView
android:id="@+id/textViewTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="40dp"
android:textSize="25sp"
android:text="@string/_02_15"
android:maxLines="1"
android:textColor="@color/colorPrimaryDark"
android:textStyle="bold"/>
<Button <Button
android:id="@+id/returnBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"

View File

@@ -1,25 +0,0 @@
<LinearLayout 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="de.hwr_berlin.it14.postgrachelor.QuestionStartFragment"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="60dp"
android:textSize="40sp"
android:text="@string/start_test" />
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:scaleX="2"
android:scaleY="2"
android:src="@drawable/ic_play_arrow" />
</LinearLayout>

View File

@@ -1,4 +1,4 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"> <resources>
<item name="ic_menu_camera" type="drawable">@android:drawable/ic_menu_camera</item> <item name="ic_menu_camera" type="drawable">@android:drawable/ic_menu_camera</item>
<item name="ic_menu_gallery" type="drawable">@android:drawable/ic_menu_gallery</item> <item name="ic_menu_gallery" type="drawable">@android:drawable/ic_menu_gallery</item>
<item name="ic_menu_slideshow" type="drawable">@android:drawable/ic_menu_slideshow</item> <item name="ic_menu_slideshow" type="drawable">@android:drawable/ic_menu_slideshow</item>

View File

@@ -19,4 +19,13 @@
<string name="launcher_icon">Launcher Icon</string> <string name="launcher_icon">Launcher Icon</string>
<string name="android_studio">Android Studio</string> <string name="android_studio">Android Studio</string>
<string name="android_studio_email">android.studio@android.com</string> <string name="android_studio_email">android.studio@android.com</string>
<string name="no_highscores_available">Highscores could not be loaded!</string>
<string name="resume_test">Resume Test!</string>
<string name="_02_15">02:15</string>
<string name="no_score">No Score</string>
<string name="no_time">No Time</string>
<string name="category">Category: %1$s</string>
<string name="no_question_available">No question available!</string>
<string name="_0">0</string>
<string name="play_a_game">Play a Game!</string>
</resources> </resources>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="83cm" height="24cm" viewBox="39 -1 1642 462" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <svg width="83cm" height="24cm" viewBox="39 -1 1642 462" xmlns="http://www.w3.org/2000/svg">
<g> <g>
<rect style="fill: #ffffff" x="40" y="0" width="45.05" height="36"/> <rect style="fill: #ffffff" x="40" y="0" width="45.05" height="36"/>
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="40" y="0" width="45.05" height="36"/> <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="40" y="0" width="45.05" height="36"/>

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB