package it.fdev.unisaconnect; import it.fdev.scraper.esse3.Esse3BasicScraper.LoadStates; import it.fdev.scraper.esse3.Esse3ScraperService; import it.fdev.unisaconnect.MainActivity.BootableFragmentsEnum; import it.fdev.unisaconnect.data.Libretto; import it.fdev.unisaconnect.data.Libretto.CorsoLibretto; import it.fdev.unisaconnect.data.LibrettoDB; import it.fdev.unisaconnect.data.SharedPrefDataManager; import it.fdev.utils.MyDateUtils; import it.fdev.utils.MySimpleFragment; import it.fdev.utils.Utils; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import com.echo.holographlibrary.Line; import com.echo.holographlibrary.LineGraph; import com.echo.holographlibrary.LineGraph.OnPointClickedListener; import com.echo.holographlibrary.LinePoint; public class FragmentLibretto extends MySimpleFragment { private final String RIEPILOGO_FLOAT_FORMAT_TYPE = "%.3f"; private SharedPrefDataManager mDataManager; private boolean alreadyStarted = false; private LibrettoDB librettoDB; private boolean sortByName = true; private boolean isUpdatingAfterResort = false; private LinearLayout riepilogoContainerView; private LinearLayout listaCorsiView; private TextView cfuConseguitiView; private TextView cfuTotaliView; private TextView avgWeightedView; private TextView avgArithView; private TextView baseMarkView; private View librettoLineGraphContainer; private LineGraph librettoLineGraph; private LinearLayout librettoGraphEsameContainerView; private TextView librettoGraphEsameNomeView; private TextView librettoGraphEsameSuperatoView; private TextView librettoNDView; private TextView lastUpdateTextView; private View lastUpdateIconView; private View sorterButtonView; private View sorterIconView; private ProgressBar sorterLoadingView; private TextView sorterTextView; private IntentFilter mIntentFilter = new IntentFilter(); private final BroadcastReceiver mHandlerBroadcast = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { onNewBroadcast(context, intent); } }; private Libretto libretto; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_libretto, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // Se non sono stati salvati i dati utente rimando al fragment dei dati mDataManager = new SharedPrefDataManager(mActivity); if (!mDataManager.loginDataExists()) { // Non sono memorizzati i dati utente Utils.createAlert(mActivity, getString(R.string.dati_errati), BootableFragmentsEnum.ACCOUNT, false); return; } mActivity.setLoadingVisible(true, true); mIntentFilter.addAction(Esse3ScraperService.BROADCAST_STATE_E3_LIBRETTO); listaCorsiView = (LinearLayout) view.findViewById(R.id.lista_corsi); riepilogoContainerView = (LinearLayout) view.findViewById(R.id.riepilogo_libretto); cfuConseguitiView = (TextView) riepilogoContainerView.findViewById(R.id.cfu_conseguiti); cfuTotaliView = (TextView) riepilogoContainerView.findViewById(R.id.cfu_totali); avgWeightedView = (TextView) riepilogoContainerView.findViewById(R.id.avg_weighted); avgArithView = (TextView) riepilogoContainerView.findViewById(R.id.avg_arithmetic); baseMarkView = (TextView) riepilogoContainerView.findViewById(R.id.base_mark); librettoLineGraphContainer = view.findViewById(R.id.libretto_line_graph_container); librettoLineGraph = (LineGraph) view.findViewById(R.id.libretto_line_graph); librettoGraphEsameContainerView = (LinearLayout) view.findViewById(R.id.libretto_graph_esame_container); librettoGraphEsameNomeView = (TextView) librettoGraphEsameContainerView.findViewById(R.id.libretto_graph_esame_nome); librettoGraphEsameSuperatoView = (TextView) librettoGraphEsameContainerView.findViewById(R.id.libretto_graph_esame_superato); // librettoGraphEsameVotoView = (TextView) librettoGraphEsameContainerView.findViewById(R.id.libretto_graph_esame_voto); librettoNDView = (TextView) view.findViewById(R.id.libretto_vuoto); lastUpdateTextView = (TextView) view.findViewById(R.id.last_update_time); lastUpdateIconView = view.findViewById(R.id.last_update_icon); sorterButtonView = view.findViewById(R.id.sorter_button); sorterIconView = view.findViewById(R.id.sorter_icon); sorterLoadingView = (ProgressBar) view.findViewById(R.id.sorter_loading); sorterTextView = (TextView) view.findViewById(R.id.sorter_text); sorterButtonView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (isUpdatingAfterResort) { return; } isUpdatingAfterResort = true; sorterIconView.setVisibility(View.GONE); // sorterTextView.setVisibility(View.GONE); sorterLoadingView.setVisibility(View.VISIBLE); new Thread(new Runnable() { // Deve essere eseguito un un nuovo thread perche altrimenti il redraw del layout viene fatto a task finito @Override // e quindi l'amimazione non verrebbe mostrata (sorterLoadingView.show -> sorterLoadingView.hide -> draw) public void run() { mActivity.runOnUiThread(new Runnable() { @Override public void run() { CharSequence text = ""; sortByName = !sortByName; mDataManager.setLibrettoSortByName(sortByName); if (sortByName) { text = resources.getText(R.string.ordina_per_nome); } else { text = resources.getText(R.string.ordina_per_data); } sorterTextView.setText(text); mostraCorsi(); sorterLoadingView.setVisibility(View.GONE); sorterIconView.setVisibility(View.VISIBLE); // sorterTextView.setVisibility(View.VISIBLE); isUpdatingAfterResort = false; } }); } }).start(); } }); sortByName = mDataManager.getLibrettoSortByName(); CharSequence text = ""; if (sortByName) { text = resources.getText(R.string.ordina_per_nome); } else { text = resources.getText(R.string.ordina_per_data); } sorterTextView.setText(text); sorterLoadingView.getIndeterminateDrawable().setColorFilter(Color.GRAY, android.graphics.PorterDuff.Mode.MULTIPLY); librettoDB = new LibrettoDB(mActivity); librettoDB.open(); } @Override public void onStop() { super.onStop(); } @Override public void onResume() { super.onResume(); mActivity.registerReceiver(mHandlerBroadcast, mIntentFilter); getLibretto(false); } @Override public void onPause() { super.onPause(); mActivity.unregisterReceiver(mHandlerBroadcast); } @Override public void onDestroy() { super.onDestroy(); try { librettoDB.close(); } catch (Exception e) { // Failed to close database } } public void onNewBroadcast(Context context, Intent intent) { try { Log.d(Utils.TAG, "BROADCAST RECEIVED: " + intent.getAction()); if (Esse3ScraperService.BROADCAST_STATE_E3_LIBRETTO.equals(intent.getAction())) { LoadStates state = (LoadStates) intent.getSerializableExtra("status"); switch (state) { case FINISHED: mostraCorsi(); break; case NO_DATA: case WRONG_DATA: Utils.createAlert(mActivity, mActivity.getString(R.string.dati_errati), BootableFragmentsEnum.ACCOUNT, false); break; case UNKNOWN_PROBLEM: default: Utils.createAlert(mActivity, mActivity.getString(R.string.problema_di_connessione_generico), null, true); break; } } } catch (Exception e) { Log.e(Utils.TAG, "onReceiveBroadcast exception", e); } } @Override public Set<Integer> getActionsToShow() { Set<Integer> actionsToShow = new HashSet<Integer>(); actionsToShow.add(R.id.action_refresh_button); if (!alreadyStarted || Esse3ScraperService.isRunning) { actionsToShow.add(R.id.action_loading_animation); } return actionsToShow; } @Override public void actionRefresh() { getLibretto(true); } public void getLibretto(boolean force) { if (!isAdded()) { return; } // librettoDB not created -> onViewCreated stopped at data check if (librettoDB == null) { return; } // Lo scraper è in esecuzione if (Esse3ScraperService.isRunning) { return; } mActivity.setLoadingVisible(true, true); Libretto libretto = librettoDB.getLibretto(); // Il libretto c'è e non devo forzare l'aggiornamento if (!force && libretto.getSize() > 0) { mostraCorsi(); mActivity.setLoadingVisible(false, false); alreadyStarted = true; return; } // Se non c'è internet rimando al fragment di errore if (!Utils.hasConnection(mActivity)) { Utils.goToInternetError(mActivity, this); return; } if (force || !alreadyStarted) { alreadyStarted = true; mActivity.startService(new Intent(mActivity, Esse3ScraperService.class).setAction(Esse3ScraperService.BROADCAST_STATE_E3_LIBRETTO)); } else { riepilogoContainerView.setVisibility(View.GONE); librettoNDView.setVisibility(View.VISIBLE); mActivity.setLoadingVisible(false, false); return; } } public void mostraCorsi() { if (!isAdded()) { return; } if (libretto == null) { libretto = librettoDB.getLibretto(); } if (libretto.getSize() == 0) { riepilogoContainerView.setVisibility(View.GONE); librettoNDView.setVisibility(View.VISIBLE); return; } aggiornaRiepilogo(libretto); String updateText = ""; if (libretto != null) { updateText = MyDateUtils.getLastUpdateString(mActivity, libretto.getFetchTime().getTime(), false); } if (!updateText.isEmpty()) { lastUpdateTextView.setText(updateText); lastUpdateTextView.setVisibility(View.VISIBLE); lastUpdateIconView.setVisibility(View.VISIBLE); } else { lastUpdateTextView.setVisibility(View.GONE); lastUpdateIconView.setVisibility(View.GONE); } LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); listaCorsiView.removeAllViews(); ArrayList<CorsoLibretto> corsiByName = libretto.getCorsiByName(); ArrayList<CorsoLibretto> corsiByDate = libretto.getCorsiByDate(); ArrayList<CorsoLibretto> corsi; if (sortByName) { corsi = corsiByName; } else { corsi = corsiByDate; } for (CorsoLibretto corso : corsi) { View rowView; if (corso.getDate() == null) { rowView = inflater.inflate(R.layout.libretto_row_with_slider, listaCorsiView, false); } else { rowView = inflater.inflate(R.layout.libretto_row, listaCorsiView, false); } TextView nameView = (TextView) rowView.findViewById(R.id.course_name); TextView cfuView = (TextView) rowView.findViewById(R.id.course_credits); final TextView markView = (TextView) rowView.findViewById(R.id.course_mark); final CorsoLibretto cCorso = corso; String name = corso.getName(); nameView.setText(name); cfuView.setText(corso.getCFU() + " CFU"); if (corso.getDate() == null) { markView.setText("ND"); SeekBar seekBarView = (SeekBar) rowView.findViewById(R.id.course_seekbar); seekBarView.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { String newMark = ""; if (progress == 0) { newMark = "ND"; } else { markView.setText(Integer.toString(progress + 17)); newMark = Integer.toString(progress + 17); } markView.setText(newMark); cCorso.setMark(progress + 17); libretto.calcolaStatistiche(); aggiornaRiepilogo(libretto); } }); } else { TextView dateView = (TextView) rowView.findViewById(R.id.course_date); dateView.setText(corso.getDateString()); String markString; if (corso.getMark() == 31) { markString = "30L"; } else if (corso.getMark() == -1) { markString = "SUP"; } else { markString = Integer.toString(corso.getMark()); } markView.setText(markString); } listaCorsiView.addView(rowView); } Line line = new Line(); int position = 1; int minVoto = Integer.MAX_VALUE, maxVoto = Integer.MIN_VALUE; final ArrayList<CorsoLibretto> coursesInsertedInGraph = new ArrayList<Libretto.CorsoLibretto>(); for (CorsoLibretto corso : corsiByDate) { int voto; voto = corso.getMark(); if (voto == 31) { voto = 30; } else if (voto == -1 || voto == 0) { continue; } if (corso.getDate() == null) { continue; } minVoto = Math.min(voto, minVoto); maxVoto = Math.max(voto, maxVoto); LinePoint point = new LinePoint(position, voto); line.addPoint(point); position++; coursesInsertedInGraph.add(corso); } if (line.getSize() < 2) { librettoLineGraphContainer.setVisibility(View.GONE); } else { line.setColor(Color.parseColor("#F4842D")); librettoLineGraph.removeAllLines(); librettoLineGraph.addLine(line); librettoLineGraph.setRangeY(minVoto - 1, maxVoto + 1); librettoLineGraph.setOnPointClickedListener(new OnPointClickedListener() { @Override public void onClick(int lineIndex, int pointIndex) { CorsoLibretto corso = coursesInsertedInGraph.get(pointIndex); librettoGraphEsameContainerView.setVisibility(View.VISIBLE); librettoGraphEsameNomeView.setText(corso.getName()); librettoGraphEsameSuperatoView.setText(getString(R.string.superato_il_con, corso.getDateString(), Integer.toString(corso.getMark()))); } }); // librettoLineGraph.setPointClicked(0,coursesInsertedInGraph.size()-1); } riepilogoContainerView.setVisibility(View.VISIBLE); librettoNDView.setVisibility(View.GONE); mActivity.setLoadingVisible(false, false); } private void aggiornaRiepilogo(Libretto libretto) { int cfuConseguiti = libretto.getCFUConseguiti(); cfuConseguitiView.setText(Integer.toString(cfuConseguiti)); int cfuTotali = libretto.getCFUTotali(); cfuTotaliView.setText(Integer.toString(cfuTotali)); float mediaAritmetica = libretto.getMediaAritmetica(); avgArithView.setText(String.format(RIEPILOGO_FLOAT_FORMAT_TYPE, mediaAritmetica)); float mediaPesata = libretto.getMediaPonderata(); avgWeightedView.setText(String.format(RIEPILOGO_FLOAT_FORMAT_TYPE, mediaPesata)); long baseMark = Math.round((mediaPesata * 110.0) / 30.0); baseMarkView.setText(Long.toString(baseMark)); } @Override public int getTitleResId() { return R.string.libretto; } }