/* * ____.____ __.____ ___ _____ * | | |/ _| | \ / _ \ ______ ______ * | | < | | / / /_\ \\____ \\____ \ * /\__| | | \| | / / | \ |_> > |_> > * \________|____|__ \______/ \____|__ / __/| __/ * \/ \/|__| |__| * * Copyright (c) 2014-2015 Paul "Marunjar" Pretsch * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * */ package org.voidsink.anewjkuapp; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import org.voidsink.anewjkuapp.base.RecyclerArrayAdapter; import org.voidsink.anewjkuapp.kusss.Assessment; import org.voidsink.anewjkuapp.kusss.AssessmentType; import org.voidsink.anewjkuapp.kusss.Grade; import org.voidsink.anewjkuapp.kusss.LvaState; import org.voidsink.anewjkuapp.kusss.LvaWithGrade; import org.voidsink.anewjkuapp.utils.AppUtils; import org.voidsink.anewjkuapp.utils.EctsSliceValue; import java.util.ArrayList; import java.util.List; import lecho.lib.hellocharts.listener.PieChartOnValueSelectListener; import lecho.lib.hellocharts.model.AbstractChartData; import lecho.lib.hellocharts.model.Axis; import lecho.lib.hellocharts.model.AxisValue; import lecho.lib.hellocharts.model.Column; import lecho.lib.hellocharts.model.ColumnChartData; import lecho.lib.hellocharts.model.ComboLineColumnChartData; import lecho.lib.hellocharts.model.PieChartData; import lecho.lib.hellocharts.model.SliceValue; import lecho.lib.hellocharts.model.SubcolumnValue; import lecho.lib.hellocharts.view.AbstractChartView; import lecho.lib.hellocharts.view.ComboLineColumnChartView; import lecho.lib.hellocharts.view.PieChartView; public class StatCardAdapter extends RecyclerArrayAdapter<StatCard, StatCardAdapter.StatViewHolder> { private static final int ADDITIONAL_SPACE = 10; private final int mTextColorPrimary; private final int mTextSizePrimary; private final int mTextColorSecondary; private final int mTextSizeSecondary; public StatCardAdapter(Context context) { super(context); TypedArray themeArray = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary, android.R.attr.textColorSecondary, android.R.attr.textSize}); this.mTextColorPrimary = themeArray.getColor(0, Color.BLACK); this.mTextColorSecondary = themeArray.getColor(1, Color.DKGRAY); this.mTextSizePrimary = (int) themeArray.getDimension(2, 12); this.mTextSizeSecondary = this.mTextSizePrimary; themeArray.recycle(); } private void initLvaListItems(StatViewHolder holder, StatCard card) { List<LvaWithGrade> mLvas = card.getLvasWithGrades(); List<LvaStatItem> lvaStats = new ArrayList<>(); LvaStatItem lva = new LvaStatItem(LvaState.OPEN, AppUtils.getECTS(LvaState.OPEN, mLvas)); if (lva.getEcts() > 0) { lvaStats.add(lva); } lva = new LvaStatItem(LvaState.DONE, AppUtils.getECTS(LvaState.DONE, mLvas)); if (lva.getEcts() > 0) { lvaStats.add(lva); } lva = new LvaStatItem(LvaState.ALL, AppUtils.getECTS(LvaState.ALL, mLvas)); if (lva.getEcts() > 0 && lvaStats.size() > 1) { lvaStats.add(lva); } holder.mItems.removeAllViews(); for (LvaStatItem item : lvaStats) { final LayoutInflater mInflater = LayoutInflater.from(getContext()); View view = mInflater.inflate(R.layout.stat_card_lva_list_entry, null, false); TextView type = (TextView) view.findViewById(R.id.stat_card_lva_list_entry_type); TextView ects = (TextView) view.findViewById(R.id.stat_card_lva_list_entry_ects); type.setText(getContext().getString(item.getType().getStringResID())); ects.setText(AppUtils.format(getContext(), "%.2f ECTS", item.getEcts())); holder.mItems.addView(view); } } private void updateLvaPlot(StatViewHolder holder, StatCard card) { List<LvaWithGrade> mLvas = card.getLvasWithGrades(); double mOpenEcts = AppUtils.getECTS(LvaState.OPEN, mLvas); double mDoneEcts = AppUtils.getECTS(LvaState.DONE, mLvas); //double minEcts = (card.getTerms() != null) ? card.getTerms().size() * 30 : 0; if (holder.mBarChart.getVisibility() == View.VISIBLE) { ComboLineColumnChartData dataSet = new ComboLineColumnChartData(); initBarChartDataSet(dataSet); ArrayList<Column> yVals = new ArrayList<>(); ArrayList<AxisValue> axisValues = new ArrayList<>(); // add series to bar chart addSerieToBarChart(yVals, axisValues, getContext().getString(LvaState.DONE.getStringResID()), mDoneEcts * 100 / (mOpenEcts + mDoneEcts), mDoneEcts, Grade.G1.getColor()); addSerieToBarChart(yVals, axisValues, getContext().getString(LvaState.OPEN.getStringResID()), mOpenEcts * 100 / (mOpenEcts + mDoneEcts), mOpenEcts, Grade.G3.getColor()); Axis xAxis = new Axis(axisValues); xAxis.setTextColor(mTextColorPrimary); xAxis.setLineColor(mTextColorSecondary); Axis yAxis = Axis.generateAxisFromRange(0, 110, 10).setHasLines(true).setName("%"); yAxis.setTextColor(mTextColorPrimary); yAxis.setLineColor(mTextColorSecondary); dataSet.setAxisXBottom(xAxis); dataSet.setAxisYLeft(yAxis); dataSet.setColumnChartData(new ColumnChartData(yVals)); holder.mBarChart.setComboLineColumnChartData(dataSet); } if (holder.mPieChart.getVisibility() == View.VISIBLE) { ArrayList<SliceValue> slices = new ArrayList<>(); ArrayList<String> captions = new ArrayList<>(); ArrayList<Integer> colors = new ArrayList<>(); // add series to pie chart addSerieToPieChart(getContext(), slices, captions, colors, getContext().getString(LvaState.DONE.getStringResID()), mDoneEcts * 100 / (mOpenEcts + mDoneEcts), mDoneEcts, null, Grade.G1.getColor()); addSerieToPieChart(getContext(), slices, captions, colors, getContext().getString(LvaState.OPEN.getStringResID()), mOpenEcts * 100 / (mOpenEcts + mDoneEcts), mOpenEcts, null, Grade.G3.getColor()); PieChartData dataSet = new PieChartData(); initPieChartDataSet(dataSet); dataSet.setValues(slices); holder.mPieChart.setPieChartData(dataSet); } } private void initBarChartDataSet(ComboLineColumnChartData dataSet) { initBaseChartDataSet(dataSet); } private void initPieChartDataSet(PieChartData dataSet) { initBaseChartDataSet(dataSet); dataSet.setCenterText1Color(mTextColorPrimary); dataSet.setCenterText1FontSize(mTextSizePrimary); dataSet.setCenterText2Color(mTextColorSecondary); dataSet.setCenterText2FontSize(mTextSizeSecondary); dataSet.setHasCenterCircle(true); dataSet.setHasLabels(true); dataSet.setHasLabelsOnlyForSelected(false); } private void initBaseChartDataSet(AbstractChartData dataSet) { } private void addSerieToBarChart(List<Column> values, List<AxisValue> axisValues, String category, double percent, double ects, int color) { if (percent > 0) { axisValues.add(new AxisValue(axisValues.size()).setLabel(category)); ArrayList<SubcolumnValue> subColumns = new ArrayList<>(); SubcolumnValue subColumn = new SubcolumnValue((float) percent, color); subColumn.setLabel(AppUtils.format(getContext(), "%.2f ECTS", ects)); subColumns.add(subColumn); Column column = new Column(subColumns); column.setHasLabels(false); column.setHasLabelsOnlyForSelected(true); values.add(column); } } private static void addSerieToPieChart(Context context, List<SliceValue> slices, List<String> captions, List<Integer> colors, String category, double percent, double ects, Grade grade, int color) { if (percent > 0) { colors.add(color); captions.add(category); SliceValue slice = new EctsSliceValue((float) percent, (float) ects, grade, color); slice.setLabel(AppUtils.format(context, "%.2f %%", percent)); slices.add(slice); } } private void initLvaPlot(final StatViewHolder holder) { if (PreferenceWrapper.getUseLvaBarChart(getContext())) { holder.mBarChart.setVisibility(View.VISIBLE); initBarChart(holder.mBarChart); holder.mPieChart.setVisibility(View.GONE); } else { holder.mPieChart.setVisibility(View.VISIBLE); initPieChart(holder.mPieChart); holder.mBarChart.setVisibility(View.GONE); } } private void initGradeListItems(StatViewHolder holder, StatCard card) { List<GradeStatItem> gradeStats = new ArrayList<>(); GradeStatItem grade = new GradeStatItem(AssessmentType.INTERIM_COURSE_ASSESSMENT, card.getAssessments(), card.isWeighted(), card.isPositiveOnly()); if (grade.getAvgGrade() > 0) { gradeStats.add(grade); } grade = new GradeStatItem(AssessmentType.FINAL_COURSE_ASSESSMENT, card.getAssessments(), card.isWeighted(), card.isPositiveOnly()); if (grade.getAvgGrade() > 0) { gradeStats.add(grade); } grade = new GradeStatItem(AssessmentType.RECOGNIZED_COURSE_CERTIFICATE, card.getAssessments(), card.isWeighted(), card.isPositiveOnly()); if (grade.getAvgGrade() > 0) { gradeStats.add(grade); } grade = new GradeStatItem(AssessmentType.RECOGNIZED_EXAM, card.getAssessments(), card.isWeighted(), card.isPositiveOnly()); if (grade.getAvgGrade() > 0) { gradeStats.add(grade); } grade = new GradeStatItem(AssessmentType.RECOGNIZED_ASSESSMENT, card.getAssessments(), card.isWeighted(), card.isPositiveOnly()); if (grade.getAvgGrade() > 0) { gradeStats.add(grade); } grade = new GradeStatItem(AssessmentType.FINAL_EXAM, card.getAssessments(), card.isWeighted(), card.isPositiveOnly()); if (grade.getAvgGrade() > 0) { gradeStats.add(grade); } grade = new GradeStatItem(AssessmentType.ALL, card.getAssessments(), card.isWeighted(), card.isPositiveOnly()); if (grade.getAvgGrade() > 0 && gradeStats.size() > 1) { gradeStats.add(grade); } if (gradeStats.size() == 0) { gradeStats.add(new GradeStatItem(AssessmentType.NONE_AVAILABLE, null, card.isWeighted(), card.isPositiveOnly())); } holder.mItems.removeAllViews(); for (GradeStatItem item : gradeStats) { final LayoutInflater mInflater = LayoutInflater.from(getContext()); View view = mInflater.inflate(R.layout.stat_card_grade_list_entry, null, false); TextView type = (TextView) view.findViewById(R.id.stat_card_grade_list_entry_type); TextView avgGrade = (TextView) view.findViewById(R.id.stat_card_grade_list_entry_grade); type.setText(getContext().getString(item.getType().getStringResID())); avgGrade.setText(AppUtils.format(getContext(), "ΓΈ %.2f", item.getAvgGrade())); holder.mItems.addView(view); } } private void updateGradePlot(StatViewHolder holder, StatCard card) { if (holder.mBarChart.getVisibility() == View.VISIBLE) { ArrayList<Column> yVals = new ArrayList<>(); ArrayList<AxisValue> axisValues = new ArrayList<>(); // add series to bar chart addSerieToBarChart(yVals, axisValues, getContext().getString(Grade.G1.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G1, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G1), Grade.G1.getColor()); addSerieToBarChart(yVals, axisValues, getContext().getString(Grade.G2.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G2, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G2), Grade.G2.getColor()); addSerieToBarChart(yVals, axisValues, getContext().getString(Grade.G3.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G3, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G3), Grade.G3.getColor()); addSerieToBarChart(yVals, axisValues, getContext().getString(Grade.G4.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G4, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G4), Grade.G4.getColor()); if (!card.isPositiveOnly()) { addSerieToBarChart(yVals, axisValues, getContext().getString(Grade.G5.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G5, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G5), Grade.G5.getColor()); } ComboLineColumnChartData dataSet = new ComboLineColumnChartData(); initBarChartDataSet(dataSet); Axis xAxis = new Axis(axisValues); xAxis.setTextColor(mTextColorPrimary); xAxis.setLineColor(mTextColorSecondary); Axis yAxis = Axis.generateAxisFromRange(0, 110, 10).setHasLines(true).setName("%"); yAxis.setTextColor(mTextColorPrimary); yAxis.setLineColor(mTextColorSecondary); dataSet.setAxisXBottom(xAxis); dataSet.setAxisYLeft(yAxis); dataSet.setColumnChartData(new ColumnChartData(yVals)); holder.mBarChart.setComboLineColumnChartData(dataSet); } if (holder.mPieChart.getVisibility() == View.VISIBLE) { ArrayList<SliceValue> slices = new ArrayList<>(); ArrayList<String> captions = new ArrayList<>(); ArrayList<Integer> colors = new ArrayList<>(); // add series to pie chart addSerieToPieChart(getContext(), slices, captions, colors, getContext().getString(Grade.G1.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G1, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G1), Grade.G1, Grade.G1.getColor()); addSerieToPieChart(getContext(), slices, captions, colors, getContext().getString(Grade.G2.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G2, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G2), Grade.G2, Grade.G2.getColor()); addSerieToPieChart(getContext(), slices, captions, colors, getContext().getString(Grade.G3.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G3, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G3), Grade.G3, Grade.G3.getColor()); addSerieToPieChart(getContext(), slices, captions, colors, getContext().getString(Grade.G4.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G4, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G4), Grade.G4, Grade.G4.getColor()); if (!card.isPositiveOnly()) { addSerieToPieChart(getContext(), slices, captions, colors, getContext().getString(Grade.G5.getStringResID()), AppUtils.getGradePercent(card.getAssessments(), Grade.G5, card.isWeighted()), AppUtils.getGradeEcts(card.getAssessments(), Grade.G5), Grade.G5, Grade.G5.getColor()); } PieChartData dataSet = new PieChartData(); initPieChartDataSet(dataSet); dataSet.setValues(slices); holder.mPieChart.setPieChartData(dataSet); } } private void initGradePlot(final StatViewHolder holder) { if (PreferenceWrapper.getUseLvaBarChart(getContext())) { holder.mBarChart.setVisibility(View.VISIBLE); initBarChart(holder.mBarChart); holder.mPieChart.setVisibility(View.GONE); } else { holder.mPieChart.setVisibility(View.VISIBLE); initPieChart(holder.mPieChart); holder.mBarChart.setVisibility(View.GONE); } } private void initBarChart(ComboLineColumnChartView barChart) { initBaseChart(barChart); } private void initPieChart(final PieChartView pieChart) { initBaseChart(pieChart); pieChart.setChartRotationEnabled(false); pieChart.setChartRotation(180, false); pieChart.setOnValueTouchListener(new PieChartOnValueSelectListener() { @Override public void onValueSelected(int arcIndex, SliceValue value) { SliceValue slice = pieChart.getPieChartData().getValues().get(arcIndex); if (slice instanceof EctsSliceValue) { pieChart.getPieChartData().setCenterText1(AppUtils.format(getContext(), "%.2f ECTS", ((EctsSliceValue) slice).getEcts())); Grade grade = ((EctsSliceValue) slice).getGrade(); if (grade != null) { pieChart.getPieChartData().setCenterText2(getContext().getString(grade.getStringResID())); } } } @Override public void onValueDeselected() { pieChart.getPieChartData().setCenterText1(null); pieChart.getPieChartData().setCenterText2(null); } }); } private void initBaseChart(AbstractChartView chart) { chart.setScrollEnabled(false); chart.setZoomEnabled(false); chart.setValueSelectionEnabled(true); } @Override public StatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.stat_card, parent, false); return new StatViewHolder(v); } @Override public void onBindViewHolder(StatViewHolder holder, int position) { StatCard item = getItem(position); switch (getItemViewType(position)) { case StatCard.TYPE_GRADE: { if (item.isWeighted()) { holder.mTitle.setText(getContext().getString(R.string.stat_title_grade_weighted)); } else { holder.mTitle.setText(getContext().getString(R.string.stat_title_grade)); } initGradeListItems(holder, item); initGradePlot(holder); updateGradePlot(holder, item); break; } case StatCard.TYPE_LVA: { holder.mTitle.setText(getContext().getString(R.string.stat_title_lva)); initLvaListItems(holder, item); initLvaPlot(holder); updateLvaPlot(holder, item); break; } } } @Override public int getItemViewType(int position) { return this.getItem(position).getType(); } private class LvaStatItem { private final LvaState mType; private final double mEcts; public LvaStatItem(LvaState type, double ects) { this.mType = type; this.mEcts = ects; } public LvaState getType() { return mType; } public double getEcts() { return mEcts; } } private class GradeStatItem { private final AssessmentType mType; private final double mAvgGrade; public GradeStatItem(AssessmentType type, List<Assessment> grades, boolean isWeighted, boolean positiveOnly) { this.mType = type; this.mAvgGrade = AppUtils.getAvgGrade(grades, isWeighted, type, positiveOnly); } public AssessmentType getType() { return mType; } public double getAvgGrade() { return mAvgGrade; } } public class StatViewHolder extends RecyclerView.ViewHolder { public final Toolbar mToolbar; public final TextView mTitle; public final LinearLayout mItems; public final ComboLineColumnChartView mBarChart; public final PieChartView mPieChart; public StatViewHolder(View itemView) { super(itemView); mToolbar = (Toolbar) itemView.findViewById(R.id.stat_card_toolbar); mTitle = (TextView) itemView.findViewById(R.id.stat_card_title); mItems = (LinearLayout) itemView.findViewById(R.id.stat_card_items); mBarChart = (ComboLineColumnChartView) itemView.findViewById(R.id.stat_card_diagram_bar); mPieChart = (PieChartView) itemView.findViewById(R.id.stat_card_diagram_pie); } } }