mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-01-31 17:52:45 +01:00
Add a summary of grades (#127)
This commit is contained in:
parent
dde5775a41
commit
0e16519baf
@ -24,12 +24,12 @@ import eu.davidea.viewholders.ExpandableViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
|
||||
public class AttendanceHeaderItem
|
||||
extends AbstractExpandableHeaderItem<AttendanceHeaderItem.HeaderViewHolder, AttendanceSubItem> {
|
||||
public class AttendanceHeader
|
||||
extends AbstractExpandableHeaderItem<AttendanceHeader.HeaderViewHolder, AttendanceSubItem> {
|
||||
|
||||
private Day day;
|
||||
|
||||
AttendanceHeaderItem(Day day) {
|
||||
AttendanceHeader(Day day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public class AttendanceHeaderItem
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AttendanceHeaderItem that = (AttendanceHeaderItem) o;
|
||||
AttendanceHeader that = (AttendanceHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(day, that.day)
|
@ -23,11 +23,11 @@ import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
|
||||
import io.github.wulkanowy.ui.main.attendance.AttendanceDialogFragment;
|
||||
|
||||
class AttendanceSubItem
|
||||
extends AbstractSectionableItem<AttendanceSubItem.SubItemViewHolder, AttendanceHeaderItem> {
|
||||
extends AbstractSectionableItem<AttendanceSubItem.SubItemViewHolder, AttendanceHeader> {
|
||||
|
||||
private AttendanceLesson lesson;
|
||||
|
||||
AttendanceSubItem(AttendanceHeaderItem header, AttendanceLesson lesson) {
|
||||
AttendanceSubItem(AttendanceHeader header, AttendanceLesson lesson) {
|
||||
super(header);
|
||||
this.lesson = lesson;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public interface AttendanceTabContract {
|
||||
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void updateAdapterList(List<AttendanceHeaderItem> headerItems);
|
||||
void updateAdapterList(List<AttendanceHeader> headerItems);
|
||||
|
||||
void onRefreshSuccess();
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class AttendanceTabFragment extends BaseFragment implements AttendanceTab
|
||||
AttendanceTabContract.Presenter presenter;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<AttendanceHeaderItem> adapter;
|
||||
FlexibleAdapter<AttendanceHeader> adapter;
|
||||
|
||||
private boolean isFragmentVisible = false;
|
||||
|
||||
@ -83,7 +83,7 @@ public class AttendanceTabFragment extends BaseFragment implements AttendanceTab
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdapterList(List<AttendanceHeaderItem> headerItems) {
|
||||
public void updateAdapterList(List<AttendanceHeader> headerItems) {
|
||||
adapter.updateDataSet(headerItems);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ public abstract class AttendanceTabModule {
|
||||
|
||||
@PerChildFragment
|
||||
@Provides
|
||||
static FlexibleAdapter<AttendanceHeaderItem> provideAdapter() {
|
||||
static FlexibleAdapter<AttendanceHeader> provideAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class AttendanceTabPresenter extends BasePresenter<AttendanceTabContract.
|
||||
|
||||
private AbstractTask loadingTask;
|
||||
|
||||
private List<AttendanceHeaderItem> headerItems = new ArrayList<>();
|
||||
private List<AttendanceHeader> headerItems = new ArrayList<>();
|
||||
|
||||
private String date;
|
||||
|
||||
@ -115,7 +115,7 @@ public class AttendanceTabPresenter extends BasePresenter<AttendanceTabContract.
|
||||
|
||||
for (Day day : dayList) {
|
||||
day.resetAttendanceLessons();
|
||||
AttendanceHeaderItem headerItem = new AttendanceHeaderItem(day);
|
||||
AttendanceHeader headerItem = new AttendanceHeader(day);
|
||||
|
||||
if (isEmptyWeek) {
|
||||
isEmptyWeek = day.getAttendanceLessons().isEmpty();
|
||||
|
@ -18,11 +18,11 @@ import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
|
||||
public class ExamsHeaderItem extends AbstractHeaderItem<ExamsHeaderItem.HeaderVieHolder> {
|
||||
public class ExamsHeader extends AbstractHeaderItem<ExamsHeader.HeaderVieHolder> {
|
||||
|
||||
private Day day;
|
||||
|
||||
ExamsHeaderItem(Day day) {
|
||||
ExamsHeader(Day day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public class ExamsHeaderItem extends AbstractHeaderItem<ExamsHeaderItem.HeaderVi
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ExamsHeaderItem that = (ExamsHeaderItem) o;
|
||||
ExamsHeader that = (ExamsHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(day, that.day)
|
@ -21,11 +21,11 @@ import io.github.wulkanowy.data.db.dao.entities.Exam;
|
||||
import io.github.wulkanowy.ui.main.exams.ExamsDialogFragment;
|
||||
|
||||
public class ExamsSubItem
|
||||
extends AbstractSectionableItem<ExamsSubItem.SubItemViewHolder, ExamsHeaderItem> {
|
||||
extends AbstractSectionableItem<ExamsSubItem.SubItemViewHolder, ExamsHeader> {
|
||||
|
||||
private Exam exam;
|
||||
|
||||
ExamsSubItem(ExamsHeaderItem header, Exam exam) {
|
||||
ExamsSubItem(ExamsHeader header, Exam exam) {
|
||||
super(header);
|
||||
this.exam = exam;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ public class ExamsTabPresenter extends BasePresenter<ExamsTabContract.View>
|
||||
|
||||
for (Day day : dayList) {
|
||||
day.resetExams();
|
||||
ExamsHeaderItem headerItem = new ExamsHeaderItem(day);
|
||||
ExamsHeader headerItem = new ExamsHeader(day);
|
||||
|
||||
List<Exam> examList = day.getExams();
|
||||
|
||||
|
@ -12,7 +12,9 @@ public interface GradesContract {
|
||||
|
||||
interface View extends BaseContract.View, SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
void updateAdapterList(List<GradeHeaderItem> headerItems);
|
||||
void updateAdapterList(List<GradesHeader> headerItems);
|
||||
|
||||
void updateSummaryAdapterList(List<GradesSummarySubItem> summarySubItems);
|
||||
|
||||
void showNoItem(boolean show);
|
||||
|
||||
@ -28,6 +30,8 @@ public interface GradesContract {
|
||||
|
||||
boolean isMenuVisible();
|
||||
|
||||
void setSummaryAverages(String calculatedValue, String predictedValue, String finalValue );
|
||||
|
||||
}
|
||||
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
@ -71,7 +71,7 @@ public class GradesDialogFragment extends DialogFragment {
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.grade_dialog, container, false);
|
||||
View view = inflater.inflate(R.layout.grades_dialog, container, false);
|
||||
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
|
@ -13,6 +13,7 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -27,17 +28,38 @@ import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public class GradesFragment extends BaseFragment implements GradesContract.View {
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_container)
|
||||
View summary;
|
||||
|
||||
@BindView(R.id.grade_fragment_details_container)
|
||||
View details;
|
||||
|
||||
@BindView(R.id.grade_fragment_recycler)
|
||||
RecyclerView recyclerView;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_recycler)
|
||||
RecyclerView summaryRecyclerView;
|
||||
|
||||
@BindView(R.id.grade_fragment_no_item_container)
|
||||
View noItemView;
|
||||
|
||||
@BindView(R.id.grade_fragment_swipe_refresh)
|
||||
SwipeRefreshLayout refreshLayout;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_predicted_average)
|
||||
TextView predictedAverage;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_calculated_average)
|
||||
TextView calculatedAverage;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_final_average)
|
||||
TextView finalAverage;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<GradeHeaderItem> adapter;
|
||||
FlexibleAdapter<GradesHeader> adapter;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<GradesSummarySubItem> summaryAdapter;
|
||||
|
||||
@Inject
|
||||
GradesContract.Presenter presenter;
|
||||
@ -66,12 +88,13 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.semester_switch, menu);
|
||||
inflater.inflate(R.menu.grades_action_menu, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_filter) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_semester_switch:
|
||||
presenter.onSemesterSwitchActive();
|
||||
CharSequence[] items = new CharSequence[]{
|
||||
getResources().getString(R.string.semester_text, 1),
|
||||
@ -88,7 +111,14 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
}
|
||||
}).show();
|
||||
return true;
|
||||
} else {
|
||||
case R.id.action_summary_switch:
|
||||
boolean isDetailsVisible = details.getVisibility() == View.VISIBLE;
|
||||
|
||||
item.setTitle(isDetailsVisible ? R.string.action_title_details : R.string.action_title_summary);
|
||||
details.setVisibility(isDetailsVisible ? View.INVISIBLE : View.VISIBLE);
|
||||
summary.setVisibility(isDetailsVisible ? View.VISIBLE : View.INVISIBLE);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
@ -96,13 +126,19 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
noItemView.setVisibility(View.GONE);
|
||||
summary.setVisibility(View.INVISIBLE);
|
||||
details.setVisibility(View.VISIBLE);
|
||||
|
||||
adapter.setAutoCollapseOnExpand(true);
|
||||
adapter.setAutoScrollOnExpand(true);
|
||||
adapter.expandItemsAtStartUp();
|
||||
summaryAdapter.setDisplayHeadersAtStartUp(true);
|
||||
|
||||
recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(view.getContext()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
summaryRecyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(view.getContext()));
|
||||
summaryRecyclerView.setAdapter(summaryAdapter);
|
||||
summaryRecyclerView.setNestedScrollingEnabled(false);
|
||||
|
||||
refreshLayout.setColorSchemeResources(android.R.color.black);
|
||||
refreshLayout.setOnRefreshListener(this);
|
||||
@ -116,6 +152,13 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSummaryAverages(String calculatedValue, String predictedValue, String finalValue) {
|
||||
calculatedAverage.setText(calculatedValue);
|
||||
predictedAverage.setText(predictedValue);
|
||||
finalAverage.setText(finalValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActivityTitle() {
|
||||
setTitle(getString(R.string.grades_text));
|
||||
@ -141,10 +184,15 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdapterList(List<GradeHeaderItem> headerItems) {
|
||||
public void updateAdapterList(List<GradesHeader> headerItems) {
|
||||
adapter.updateDataSet(headerItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSummaryAdapterList(List<GradesSummarySubItem> summarySubItems) {
|
||||
summaryAdapter.updateDataSet(summarySubItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccessNoGrade() {
|
||||
showMessage(R.string.snackbar_no_grades);
|
||||
|
@ -20,14 +20,14 @@ import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.utils.AnimationUtils;
|
||||
import io.github.wulkanowy.utils.GradeUtils;
|
||||
|
||||
public class GradeHeaderItem
|
||||
extends AbstractExpandableHeaderItem<GradeHeaderItem.HeaderViewHolder, GradesSubItem> {
|
||||
public class GradesHeader
|
||||
extends AbstractExpandableHeaderItem<GradesHeader.HeaderViewHolder, GradesSubItem> {
|
||||
|
||||
private Subject subject;
|
||||
|
||||
private final boolean isShowSummary;
|
||||
|
||||
GradeHeaderItem(Subject subject, boolean isShowSummary) {
|
||||
GradesHeader(Subject subject, boolean isShowSummary) {
|
||||
this.subject = subject;
|
||||
this.isShowSummary = isShowSummary;
|
||||
}
|
||||
@ -38,7 +38,7 @@ public class GradeHeaderItem
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GradeHeaderItem that = (GradeHeaderItem) o;
|
||||
GradesHeader that = (GradesHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(subject, that.subject)
|
||||
@ -54,7 +54,7 @@ public class GradeHeaderItem
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grade_header;
|
||||
return R.layout.grades_header;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -126,7 +126,7 @@ public class GradeHeaderItem
|
||||
}
|
||||
|
||||
private String getGradesAverageString() {
|
||||
float average = GradeUtils.calculate(item.getGradeList());
|
||||
float average = GradeUtils.calculateWeightedAverage(item.getGradeList());
|
||||
|
||||
if (average < 0) {
|
||||
return resources.getString(R.string.info_no_average);
|
@ -12,7 +12,12 @@ public abstract class GradesModule {
|
||||
abstract GradesContract.Presenter provideGradesPresenter(GradesPresenter gradesPresenter);
|
||||
|
||||
@Provides
|
||||
static FlexibleAdapter<GradeHeaderItem> provideGradesAdapter() {
|
||||
static FlexibleAdapter<GradesHeader> provideGradesAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
|
||||
@Provides
|
||||
static FlexibleAdapter<GradesSummarySubItem> provideGradesSummaryAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import org.threeten.bp.LocalDate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -18,6 +19,7 @@ import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.ui.base.BasePresenter;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
import io.github.wulkanowy.utils.FabricUtils;
|
||||
import io.github.wulkanowy.utils.GradeUtils;
|
||||
import io.github.wulkanowy.utils.async.AbstractTask;
|
||||
import io.github.wulkanowy.utils.async.AsyncListeners;
|
||||
|
||||
@ -31,12 +33,20 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
|
||||
private OnFragmentIsReadyListener listener;
|
||||
|
||||
private List<GradeHeaderItem> headerItems = new ArrayList<>();
|
||||
private List<GradesHeader> headerItems = new ArrayList<>();
|
||||
|
||||
private List<GradesSummarySubItem> summarySubItems = new ArrayList<>();
|
||||
|
||||
private boolean isFirstSight = false;
|
||||
|
||||
private int semesterName;
|
||||
|
||||
private float finalAverage;
|
||||
|
||||
private float predictedAverage;
|
||||
|
||||
private float calculatedAverage;
|
||||
|
||||
@Inject
|
||||
GradesPresenter(RepositoryContract repository) {
|
||||
super(repository);
|
||||
@ -56,7 +66,6 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
|
||||
if (!isFirstSight) {
|
||||
isFirstSight = true;
|
||||
|
||||
reloadGrades();
|
||||
}
|
||||
}
|
||||
@ -76,12 +85,6 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
.putCustomAttribute("Name", semesterName));
|
||||
}
|
||||
|
||||
private void reloadGrades() {
|
||||
loadingTask = new AbstractTask();
|
||||
loadingTask.setOnFirstLoadingListener(this);
|
||||
loadingTask.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentVisible(boolean isVisible) {
|
||||
if (isVisible) {
|
||||
@ -140,13 +143,17 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
boolean isShowSummary = getRepository().getSharedRepo().isShowGradesSummary();
|
||||
|
||||
headerItems = new ArrayList<>();
|
||||
summarySubItems = new ArrayList<>();
|
||||
|
||||
for (Subject subject : subjectList) {
|
||||
subject.resetGradeList();
|
||||
List<Grade> gradeList = subject.getGradeList();
|
||||
|
||||
GradesSummaryHeader summaryHeader = new GradesSummaryHeader(subject, GradeUtils.calculateWeightedAverage(gradeList));
|
||||
summarySubItems.add(new GradesSummarySubItem(summaryHeader, subject));
|
||||
|
||||
if (!gradeList.isEmpty()) {
|
||||
GradeHeaderItem headerItem = new GradeHeaderItem(subject, isShowSummary);
|
||||
GradesHeader headerItem = new GradesHeader(subject, isShowSummary);
|
||||
|
||||
List<GradesSubItem> subItems = new ArrayList<>();
|
||||
|
||||
@ -159,6 +166,10 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
headerItems.add(headerItem);
|
||||
}
|
||||
}
|
||||
|
||||
finalAverage = GradeUtils.calculateSubjectsAverage(subjectList, false);
|
||||
predictedAverage = GradeUtils.calculateSubjectsAverage(subjectList, true);
|
||||
calculatedAverage = GradeUtils.calculateDetailedSubjectsAverage(subjectList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -170,9 +181,35 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
public void onEndLoadingAsync(boolean result, Exception exception) {
|
||||
getView().showNoItem(headerItems.isEmpty());
|
||||
getView().updateAdapterList(headerItems);
|
||||
|
||||
setSummaryAverages();
|
||||
getView().updateSummaryAdapterList(summarySubItems);
|
||||
|
||||
listener.onFragmentIsReady();
|
||||
}
|
||||
|
||||
private void setSummaryAverages() {
|
||||
getView().setSummaryAverages(
|
||||
getFormattedAverage(calculatedAverage),
|
||||
getFormattedAverage(predictedAverage),
|
||||
getFormattedAverage(finalAverage)
|
||||
);
|
||||
}
|
||||
|
||||
private String getFormattedAverage(float average) {
|
||||
if (-1.0f == average) {
|
||||
return "-- --";
|
||||
}
|
||||
|
||||
return String.format(Locale.FRANCE, "%.2f", average);
|
||||
}
|
||||
|
||||
private void reloadGrades() {
|
||||
loadingTask = new AbstractTask();
|
||||
loadingTask.setOnFirstLoadingListener(this);
|
||||
loadingTask.execute();
|
||||
}
|
||||
|
||||
private void cancelAsyncTasks() {
|
||||
if (refreshTask != null) {
|
||||
refreshTask.cancel(true);
|
||||
|
@ -21,7 +21,7 @@ import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.utils.GradeUtils;
|
||||
|
||||
public class GradesSubItem
|
||||
extends AbstractSectionableItem<GradesSubItem.SubItemViewHolder, GradeHeaderItem> {
|
||||
extends AbstractSectionableItem<GradesSubItem.SubItemViewHolder, GradesHeader> {
|
||||
|
||||
private Grade grade;
|
||||
|
||||
@ -29,7 +29,7 @@ public class GradesSubItem
|
||||
|
||||
private View subjectAlertImage;
|
||||
|
||||
GradesSubItem(GradeHeaderItem header, Grade grade) {
|
||||
GradesSubItem(GradesHeader header, Grade grade) {
|
||||
super(header);
|
||||
this.grade = grade;
|
||||
}
|
||||
@ -64,7 +64,7 @@ public class GradesSubItem
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grade_subitem;
|
||||
return R.layout.grades_subitem;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,87 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.items.AbstractHeaderItem;
|
||||
import eu.davidea.flexibleadapter.items.IFlexible;
|
||||
import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
|
||||
class GradesSummaryHeader extends AbstractHeaderItem<GradesSummaryHeader.HeaderViewHolder> {
|
||||
|
||||
private Subject subject;
|
||||
|
||||
private String average;
|
||||
|
||||
GradesSummaryHeader(Subject subject, float average) {
|
||||
this.subject = subject;
|
||||
this.average = String.format(Locale.FRANCE, "%.2f", average);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GradesSummaryHeader that = (GradesSummaryHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(subject, that.subject)
|
||||
.append(average, that.average)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(subject)
|
||||
.append(average)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grades_summary_header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
|
||||
return new HeaderViewHolder(view, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, HeaderViewHolder holder, int position, List<Object> payloads) {
|
||||
holder.onBind(subject, average);
|
||||
}
|
||||
|
||||
static class HeaderViewHolder extends FlexibleViewHolder {
|
||||
|
||||
@BindView(R.id.grades_summary_header_name)
|
||||
TextView name;
|
||||
|
||||
@BindView(R.id.grades_summary_header_average)
|
||||
TextView average;
|
||||
|
||||
HeaderViewHolder(View view, FlexibleAdapter adapter) {
|
||||
super(view, adapter);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
|
||||
void onBind(Subject item, String value) {
|
||||
name.setText(item.getName());
|
||||
average.setText("-1,00".equals(value) ? "" : value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.items.AbstractSectionableItem;
|
||||
import eu.davidea.flexibleadapter.items.IFlexible;
|
||||
import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
|
||||
public class GradesSummarySubItem
|
||||
extends AbstractSectionableItem<GradesSummarySubItem.SubItemViewHolder, GradesSummaryHeader> {
|
||||
|
||||
private Subject subject;
|
||||
|
||||
public GradesSummarySubItem(GradesSummaryHeader header, Subject subject) {
|
||||
super(header);
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GradesSummarySubItem that = (GradesSummarySubItem) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(subject, that.subject)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(subject)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grades_summary_subitem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubItemViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
|
||||
return new SubItemViewHolder(view, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, SubItemViewHolder holder, int position, List<Object> payloads) {
|
||||
holder.onBind(subject);
|
||||
}
|
||||
|
||||
static class SubItemViewHolder extends FlexibleViewHolder {
|
||||
|
||||
@BindView(R.id.grades_summary_subitem_final_grade)
|
||||
TextView finalGrade;
|
||||
|
||||
@BindView(R.id.grades_summary_subitem_predicted_grade)
|
||||
TextView predictedGrade;
|
||||
|
||||
SubItemViewHolder(View view, FlexibleAdapter adapter) {
|
||||
super(view, adapter);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
|
||||
void onBind(Subject item) {
|
||||
predictedGrade.setText(item.getPredictedRating());
|
||||
finalGrade.setText(item.getFinalRating());
|
||||
}
|
||||
}
|
||||
}
|
@ -24,12 +24,12 @@ import eu.davidea.viewholders.ExpandableViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
|
||||
public class TimetableHeaderItem
|
||||
extends AbstractExpandableHeaderItem<TimetableHeaderItem.HeaderViewHolder, TimetableSubItem> {
|
||||
public class TimetableHeader
|
||||
extends AbstractExpandableHeaderItem<TimetableHeader.HeaderViewHolder, TimetableSubItem> {
|
||||
|
||||
private Day day;
|
||||
|
||||
TimetableHeaderItem(Day day) {
|
||||
TimetableHeader(Day day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public class TimetableHeaderItem
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TimetableHeaderItem that = (TimetableHeaderItem) o;
|
||||
TimetableHeader that = (TimetableHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(day, that.day)
|
@ -25,11 +25,11 @@ import io.github.wulkanowy.ui.main.timetable.TimetableDialogFragment;
|
||||
|
||||
|
||||
public class TimetableSubItem
|
||||
extends AbstractSectionableItem<TimetableSubItem.SubItemViewHolder, TimetableHeaderItem> {
|
||||
extends AbstractSectionableItem<TimetableSubItem.SubItemViewHolder, TimetableHeader> {
|
||||
|
||||
private TimetableLesson lesson;
|
||||
|
||||
TimetableSubItem(TimetableHeaderItem header, TimetableLesson lesson) {
|
||||
TimetableSubItem(TimetableHeader header, TimetableLesson lesson) {
|
||||
super(header);
|
||||
this.lesson = lesson;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public interface TimetableTabContract {
|
||||
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void updateAdapterList(List<TimetableHeaderItem> headerItems);
|
||||
void updateAdapterList(List<TimetableHeader> headerItems);
|
||||
|
||||
void expandItem(int item);
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class TimetableTabFragment extends BaseFragment implements TimetableTabCo
|
||||
TimetableTabContract.Presenter presenter;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<TimetableHeaderItem> adapter;
|
||||
FlexibleAdapter<TimetableHeader> adapter;
|
||||
|
||||
private boolean isFragmentVisible = false;
|
||||
|
||||
@ -86,7 +86,7 @@ public class TimetableTabFragment extends BaseFragment implements TimetableTabCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdapterList(List<TimetableHeaderItem> headerItems) {
|
||||
public void updateAdapterList(List<TimetableHeader> headerItems) {
|
||||
adapter.updateDataSet(headerItems);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ public abstract class TimetableTabModule {
|
||||
|
||||
@PerChildFragment
|
||||
@Provides
|
||||
static FlexibleAdapter<TimetableHeaderItem> provideTimetableAdapter() {
|
||||
static FlexibleAdapter<TimetableHeader> provideTimetableAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class TimetableTabPresenter extends BasePresenter<TimetableTabContract.Vi
|
||||
|
||||
private AbstractTask loadingTask;
|
||||
|
||||
private List<TimetableHeaderItem> headerItems = new ArrayList<>();
|
||||
private List<TimetableHeader> headerItems = new ArrayList<>();
|
||||
|
||||
private String date;
|
||||
|
||||
@ -117,7 +117,7 @@ public class TimetableTabPresenter extends BasePresenter<TimetableTabContract.Vi
|
||||
|
||||
for (Day day : dayList) {
|
||||
day.resetTimetableLessons();
|
||||
TimetableHeaderItem headerItem = new TimetableHeaderItem(day);
|
||||
TimetableHeader headerItem = new TimetableHeader(day);
|
||||
|
||||
if (isFreeWeek) {
|
||||
isFreeWeek = day.getFreeDay();
|
||||
|
@ -6,6 +6,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
|
||||
public final class GradeUtils {
|
||||
|
||||
@ -16,53 +17,33 @@ public final class GradeUtils {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static float calculate(List<Grade> gradeList) {
|
||||
public static float calculateWeightedAverage(List<Grade> gradeList) {
|
||||
|
||||
float counter = 0f;
|
||||
float denominator = 0f;
|
||||
|
||||
for (Grade grade : gradeList) {
|
||||
int integerWeight = getIntegerForWeightOfGrade(grade.getWeight());
|
||||
float floatValue = getMathematicalValueOfGrade(grade.getValue());
|
||||
int weight = getWeightValue(grade.getWeight());
|
||||
float value = getWeightedGradeValue(grade.getValue());
|
||||
|
||||
if (floatValue != -1f) {
|
||||
counter += floatValue * integerWeight;
|
||||
denominator += integerWeight;
|
||||
if (value != -1.0f) {
|
||||
counter += value * weight;
|
||||
denominator += weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == 0f) {
|
||||
return -1f;
|
||||
} else {
|
||||
return -1.0f;
|
||||
}
|
||||
return counter / denominator;
|
||||
}
|
||||
|
||||
public static float calculateSubjectsAverage(List<Subject> subjectList, boolean usePredicted) {
|
||||
return calculateSubjectsAverage(subjectList, usePredicted, false);
|
||||
}
|
||||
|
||||
private static float getMathematicalValueOfGrade(String valueOfGrade) {
|
||||
if (valueOfGrade.matches("[-|+|=]{0,2}[0-6]")
|
||||
|| valueOfGrade.matches("[0-6][-|+|=]{0,2}")) {
|
||||
if (valueOfGrade.matches("[-][0-6]")
|
||||
|| valueOfGrade.matches("[0-6][-]")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[-]", "");
|
||||
return Float.valueOf(replacedValue) - 0.33f;
|
||||
} else if (valueOfGrade.matches("[+][0-6]")
|
||||
|| valueOfGrade.matches("[0-6][+]")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[+]", "");
|
||||
return Float.valueOf((replacedValue)) + 0.33f;
|
||||
} else if (valueOfGrade.matches("[-|=]{1,2}[0-6]")
|
||||
|| valueOfGrade.matches("[0-6][-|=]{1,2}")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[-|=]{1,2}", "");
|
||||
return Float.valueOf((replacedValue)) - 0.5f;
|
||||
} else {
|
||||
return Float.valueOf(valueOfGrade);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getIntegerForWeightOfGrade(String weightOfGrade) {
|
||||
return Integer.valueOf(weightOfGrade.substring(0, weightOfGrade.length() - 3));
|
||||
public static float calculateDetailedSubjectsAverage(List<Subject> subjectList) {
|
||||
return calculateSubjectsAverage(subjectList, false, true);
|
||||
}
|
||||
|
||||
public static int getValueColor(String value) {
|
||||
@ -93,4 +74,80 @@ public final class GradeUtils {
|
||||
return R.color.default_grade;
|
||||
}
|
||||
}
|
||||
|
||||
private static float calculateSubjectsAverage(List<Subject> subjectList, boolean usePredicted, boolean useSubjectsAverages) {
|
||||
float counter = 0f;
|
||||
float denominator = 0f;
|
||||
|
||||
for (Subject subject : subjectList) {
|
||||
float value;
|
||||
|
||||
if (useSubjectsAverages) {
|
||||
value = calculateWeightedAverage(subject.getGradeList());
|
||||
} else {
|
||||
value = getGradeValue(usePredicted ? subject.getPredictedRating() : subject.getFinalRating());
|
||||
}
|
||||
|
||||
if (value != -1.0f) {
|
||||
counter += Math.round(value);
|
||||
denominator++;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == 0) {
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
return counter / denominator;
|
||||
}
|
||||
|
||||
private static float getGradeValue(String grade) {
|
||||
if (validGradePattern.matcher(grade).matches()) {
|
||||
return getWeightedGradeValue(grade);
|
||||
}
|
||||
|
||||
return getVerbalGradeValue(grade);
|
||||
}
|
||||
|
||||
private static float getVerbalGradeValue(String grade) {
|
||||
switch (grade) {
|
||||
case "celujący":
|
||||
return 6f;
|
||||
case "bardzo dobry":
|
||||
return 5f;
|
||||
case "dobry":
|
||||
return 4f;
|
||||
case "dostateczny":
|
||||
return 3f;
|
||||
case "dopuszczający":
|
||||
return 2f;
|
||||
case "niedostateczny":
|
||||
return 1f;
|
||||
default:
|
||||
return -1f;
|
||||
}
|
||||
}
|
||||
|
||||
private static float getWeightedGradeValue(String value) {
|
||||
if (validGradePattern.matcher(value).matches()) {
|
||||
if (value.matches("[-][0-6]") || value.matches("[0-6][-]")) {
|
||||
String replacedValue = value.replaceAll("[-]", "");
|
||||
return Float.valueOf(replacedValue) - 0.33f;
|
||||
} else if (value.matches("[+][0-6]") || value.matches("[0-6][+]")) {
|
||||
String replacedValue = value.replaceAll("[+]", "");
|
||||
return Float.valueOf((replacedValue)) + 0.33f;
|
||||
} else if (value.matches("[-|=]{1,2}[0-6]") || value.matches("[0-6][-|=]{1,2}")) {
|
||||
String replacedValue = value.replaceAll("[-|=]{1,2}", "");
|
||||
return Float.valueOf((replacedValue)) - 0.5f;
|
||||
} else {
|
||||
return Float.valueOf(value);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getWeightValue(String weightOfGrade) {
|
||||
return Integer.valueOf(weightOfGrade.substring(0, weightOfGrade.length() - 3));
|
||||
}
|
||||
}
|
||||
|
10
app/src/main/res/drawable/ic_action_menu_semester.xml
Normal file
10
app/src/main/res/drawable/ic_action_menu_semester.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z" />
|
||||
</vector>
|
13
app/src/main/res/drawable/ic_action_menu_summary.xml
Normal file
13
app/src/main/res/drawable/ic_action_menu_summary.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M11,7h2v2h-2zM11,11h2v6h-2z" />
|
||||
<path
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M12,2a10,10 0,1 0,0 20,10 10,0 0,0 0,-20zM12,20a8,8 0,1 1,0 -16,8 8,0 0,1
|
||||
0,16z" />
|
||||
</vector>
|
@ -1,4 +1,4 @@
|
||||
<!-- drawable/exclamation.xml -->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
|
@ -1,5 +0,0 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
|
||||
</vector>
|
@ -6,6 +6,138 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context="io.github.wulkanowy.ui.main.grades.GradesFragment">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/grade_fragment_swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/grade_fragment_details_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/grade_fragment_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</FrameLayout>
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:id="@+id/grade_fragment_summary_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:descendantFocusability="blocksDescendants">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/grade_fragment_summary_calculated_container"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_toLeftOf="@id/grade_fragment_summary_final_container"
|
||||
android:layout_toStartOf="@id/grade_fragment_summary_final_container">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_fragment_summary_calculated_average_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center"
|
||||
android:text="@string/grades_summary_calculated_average"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_fragment_summary_calculated_average"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/grade_fragment_summary_calculated_average_text"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="6,00"
|
||||
android:textSize="21sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/grade_fragment_summary_final_container"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="20dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_fragment_summary_final_average_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center"
|
||||
android:minLines="2"
|
||||
android:text="@string/grades_summary_final_average"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_fragment_summary_final_average"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/grade_fragment_summary_final_average_text"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="6,00"
|
||||
android:textSize="21sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/grade_fragment_summary_predicted_container"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_toEndOf="@id/grade_fragment_summary_final_container"
|
||||
android:layout_toRightOf="@id/grade_fragment_summary_final_container">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_fragment_summary_predicted_average_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center"
|
||||
android:maxLines="2"
|
||||
android:text="@string/grades_summary_predicted_average"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_fragment_summary_predicted_average"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/grade_fragment_summary_predicted_average_text"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="6,00"
|
||||
android:textSize="21sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/grade_fragment_summary_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/grade_fragment_summary_calculated_container"
|
||||
android:layout_marginTop="20dp" />
|
||||
</RelativeLayout>
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/grade_fragment_no_item_container"
|
||||
android:layout_width="match_parent"
|
||||
@ -30,21 +162,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="46dp"
|
||||
android:text="@string/fragment_no_grades"
|
||||
android:gravity="center"
|
||||
android:text="@string/fragment_no_grades"
|
||||
android:textSize="20sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/grade_fragment_swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/grade_fragment_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
@ -51,6 +51,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/grade_header_average_text"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/info_grades_predicted_rating"
|
||||
android:textColor="@color/secondary_text"
|
||||
@ -61,8 +63,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/grade_header_average_text"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_toEndOf="@+id/grade_header_predicted_rating_text"
|
||||
android:layout_toRightOf="@+id/grade_header_predicted_rating_text"
|
34
app/src/main/res/layout/grades_summary_header.xml
Normal file
34
app/src/main/res/layout/grades_summary_header.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#EEE"
|
||||
android:paddingBottom="7dp"
|
||||
android:paddingLeft="20dp"
|
||||
android:paddingRight="20dp"
|
||||
android:paddingTop="7dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grades_summary_header_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="40dp"
|
||||
android:layout_marginRight="40dp"
|
||||
android:layout_toLeftOf="@id/grades_summary_header_average"
|
||||
android:layout_toStartOf="@id/grades_summary_header_average"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grades_summary_header_average"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="end"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</RelativeLayout>
|
75
app/src/main/res/layout/grades_summary_subitem.xml
Normal file
75
app/src/main/res/layout/grades_summary_subitem.xml
Normal file
@ -0,0 +1,75 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/grades_summary_subitem_predicted_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/ic_border"
|
||||
android:minHeight="35dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grades_summary_subitem_predicted_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:text="@string/grades_predicted_rating"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grades_summary_subitem_predicted_grade"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="25dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@id/grades_summary_subitem_predicted_name"
|
||||
android:layout_toRightOf="@id/grades_summary_subitem_predicted_name"
|
||||
android:gravity="end"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="12sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/grades_summary_subitem_final_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/grades_summary_subitem_predicted_container"
|
||||
android:background="@drawable/ic_border"
|
||||
android:minHeight="35dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grades_summary_subitem_final_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:text="@string/grades_final_rating"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grades_summary_subitem_final_grade"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="25dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@id/grades_summary_subitem_final_name"
|
||||
android:layout_toRightOf="@id/grades_summary_subitem_final_name"
|
||||
android:gravity="end"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="12sp" />
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
20
app/src/main/res/menu/grades_action_menu.xml
Normal file
20
app/src/main/res/menu/grades_action_menu.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<menu 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"
|
||||
tools:context="io.github.wulkanowy.timetable.MainActivity">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_semester_switch"
|
||||
android:icon="@drawable/ic_action_menu_semester"
|
||||
android:orderInCategory="2"
|
||||
android:title="@string/switch_semester"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_summary_switch"
|
||||
android:icon="@drawable/ic_action_menu_summary"
|
||||
android:orderInCategory="1"
|
||||
android:title="@string/action_title_summary"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
</menu>
|
@ -1,13 +0,0 @@
|
||||
<menu 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"
|
||||
tools:context="io.github.wulkanowy.timetable.MainActivity"
|
||||
>
|
||||
<item
|
||||
android:id="@+id/action_filter"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/switch_semester"
|
||||
android:icon="@drawable/ic_filter_list_black_24dp"
|
||||
app:showAsAction="always"
|
||||
/>
|
||||
</menu>
|
@ -81,6 +81,9 @@
|
||||
<string name="info_free_week">Brak lekcji w tym tygodniu</string>
|
||||
<string name="timetable_subitem_room">Sala %s</string>
|
||||
|
||||
<string name="grades_predicted_rating">Przewidywana</string>
|
||||
<string name="grades_final_rating">Końcowa</string>
|
||||
|
||||
<plurals name="numberOfGradesPlurals">
|
||||
<item quantity="one">%d ocena</item>
|
||||
<item quantity="few">%d oceny</item>
|
||||
@ -154,4 +157,10 @@
|
||||
<string name="exams_no_entries">Brak sprawdzianów w tym tygodniu</string>
|
||||
<string name="exams_type">Typ</string>
|
||||
<string name="exams_dialog_entry_date">Data wpisu</string>
|
||||
|
||||
<string name="grades_summary_calculated_average">Obliczona średnia</string>
|
||||
<string name="grades_summary_predicted_average">Szacowana średnia</string>
|
||||
<string name="grades_summary_final_average">Końcowa średnia</string>
|
||||
<string name="action_title_summary">Podsumowanie</string>
|
||||
<string name="action_title_details">Szczegóły</string>
|
||||
</resources>
|
||||
|
@ -80,6 +80,9 @@
|
||||
<string name="info_grades_final_rating">Final: %1$s</string>
|
||||
<string name="info_free_week">No lesson in this week</string>
|
||||
|
||||
<string name="grades_predicted_rating">Predicted</string>
|
||||
<string name="grades_final_rating">Final</string>
|
||||
|
||||
<string name="timetable_subitem_room">Room %s</string>
|
||||
|
||||
<plurals name="numberOfGradesPlurals">
|
||||
@ -149,4 +152,10 @@
|
||||
<string name="exams_no_entries">No exams in this week</string>
|
||||
<string name="exams_type">Type</string>
|
||||
<string name="exams_dialog_entry_date">Date of entry</string>
|
||||
|
||||
<string name="grades_summary_calculated_average">Calculated average</string>
|
||||
<string name="grades_summary_predicted_average">Predicted average</string>
|
||||
<string name="grades_summary_final_average">Final average</string>
|
||||
<string name="action_title_summary">Summary</string>
|
||||
<string name="action_title_details">Details</string>
|
||||
</resources>
|
||||
|
@ -1,6 +1,5 @@
|
||||
package io.github.wulkanowy.utils;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -8,11 +7,14 @@ import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class GradeUtilsTest {
|
||||
|
||||
@Test
|
||||
public void averageTest() {
|
||||
public void weightedAverageTest() {
|
||||
List<Grade> gradeList = new ArrayList<>();
|
||||
gradeList.add(new Grade().setValue("np.").setWeight("1,00"));
|
||||
gradeList.add(new Grade().setValue("-5").setWeight("10,00"));
|
||||
@ -29,31 +31,48 @@ public class GradeUtilsTest {
|
||||
gradeList1.add(new Grade().setValue("5+").setWeight("10,00"));
|
||||
gradeList1.add(new Grade().setValue("5").setWeight("10,00"));
|
||||
|
||||
Assert.assertEquals(4.8f, GradeUtils.calculate(gradeList), 0.0f);
|
||||
Assert.assertEquals(4.8f, GradeUtils.calculate(gradeList1), 0.0f);
|
||||
assertEquals(4.8f, GradeUtils.calculateWeightedAverage(gradeList), 0.0f);
|
||||
assertEquals(4.8f, GradeUtils.calculateWeightedAverage(gradeList1), 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorAverageTest() {
|
||||
public void subjectsAverageTest() {
|
||||
List<Subject> subjectList = new ArrayList<>();
|
||||
subjectList.add(new Subject().setPredictedRating("2").setFinalRating("3"));
|
||||
subjectList.add(new Subject().setPredictedRating("niedostateczny").setFinalRating("dopuszczający"));
|
||||
subjectList.add(new Subject().setPredictedRating("dostateczny").setFinalRating("dobry"));
|
||||
subjectList.add(new Subject().setPredictedRating("bardzo dobry").setFinalRating("celujący"));
|
||||
subjectList.add(new Subject().setPredictedRating("2/3").setFinalRating("-4"));
|
||||
|
||||
assertEquals(3.8f, GradeUtils.calculateSubjectsAverage(subjectList, false), 0.0f);
|
||||
assertEquals(2.75f, GradeUtils.calculateSubjectsAverage(subjectList, true), 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void abnormalAverageTest() {
|
||||
List<Grade> gradeList = new ArrayList<>();
|
||||
gradeList.add(new Grade().setValue("np.").setWeight("1,00"));
|
||||
|
||||
Assert.assertEquals(-1f, GradeUtils.calculate(gradeList), 0.0f);
|
||||
List<Subject> subjectList = new ArrayList<>();
|
||||
subjectList.add(new Subject().setFinalRating("nieklasyfikowany"));
|
||||
|
||||
assertEquals(-1f, GradeUtils.calculateWeightedAverage(gradeList), 0.0f);
|
||||
assertEquals(-1f, GradeUtils.calculateSubjectsAverage(subjectList, false), 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getValueColor() {
|
||||
Assert.assertEquals(R.color.six_grade, GradeUtils.getValueColor("-6"));
|
||||
Assert.assertEquals(R.color.five_grade, GradeUtils.getValueColor("--5"));
|
||||
Assert.assertEquals(R.color.four_grade, GradeUtils.getValueColor("=4"));
|
||||
Assert.assertEquals(R.color.three_grade, GradeUtils.getValueColor("3-"));
|
||||
Assert.assertEquals(R.color.two_grade, GradeUtils.getValueColor("2--"));
|
||||
Assert.assertEquals(R.color.two_grade, GradeUtils.getValueColor("2="));
|
||||
Assert.assertEquals(R.color.one_grade, GradeUtils.getValueColor("1+"));
|
||||
Assert.assertEquals(R.color.one_grade, GradeUtils.getValueColor("+1"));
|
||||
Assert.assertEquals(R.color.default_grade, GradeUtils.getValueColor("6 (.XI)"));
|
||||
Assert.assertEquals(R.color.default_grade, GradeUtils.getValueColor("Np"));
|
||||
Assert.assertEquals(R.color.default_grade, GradeUtils.getValueColor("7"));
|
||||
Assert.assertEquals(R.color.default_grade, GradeUtils.getValueColor(""));
|
||||
public void getValueColorTest() {
|
||||
assertEquals(R.color.six_grade, GradeUtils.getValueColor("-6"));
|
||||
assertEquals(R.color.five_grade, GradeUtils.getValueColor("--5"));
|
||||
assertEquals(R.color.four_grade, GradeUtils.getValueColor("=4"));
|
||||
assertEquals(R.color.three_grade, GradeUtils.getValueColor("3-"));
|
||||
assertEquals(R.color.two_grade, GradeUtils.getValueColor("2--"));
|
||||
assertEquals(R.color.two_grade, GradeUtils.getValueColor("2="));
|
||||
assertEquals(R.color.one_grade, GradeUtils.getValueColor("1+"));
|
||||
assertEquals(R.color.one_grade, GradeUtils.getValueColor("+1"));
|
||||
assertEquals(R.color.default_grade, GradeUtils.getValueColor("6 (.XI)"));
|
||||
assertEquals(R.color.default_grade, GradeUtils.getValueColor("Np"));
|
||||
assertEquals(R.color.default_grade, GradeUtils.getValueColor("7"));
|
||||
assertEquals(R.color.default_grade, GradeUtils.getValueColor(""));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user