diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index a9aedd3..f033de4 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -537,7 +537,7 @@ public class MainActivity extends AppCompatActivity @Override public void onLogin(LoginToken token, boolean enteringOnlineMode) { - toLoginState(token.getUsername(), token.getEmail(), getDefaultFragmentAfterLogin(), enteringOnlineMode); + toLoginState(token.getFullName(), token.getEmail(), getDefaultFragmentAfterLogin(), enteringOnlineMode); } @Override diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java index 4b85503..c1e32c9 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java @@ -1,66 +1,115 @@ package de.sebse.fuplanner.fragments; +import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import java.util.ArrayList; + import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.ModulesFragment.OnModulesFragmentInteractionListener; +import de.sebse.fuplanner.services.KVV.types.Lecturer; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Semester; +import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder; +import de.sebse.fuplanner.tools.ui.StringViewHolder; /** * {@link RecyclerView.Adapter} that can display a {@link Modules.Module} and makes a call to the * specified {@link OnModulesFragmentInteractionListener}. */ -class ModulesAdapter extends RecyclerView.Adapter { +class ModulesAdapter extends RecyclerView.Adapter { + + private static final int TYPE_HEADER = 0; + private static final int TYPE_ITEM = 2; private Modules mValues; private final OnModulesFragmentInteractionListener mListener; + private final ArrayList> mPositionalData; ModulesAdapter(OnModulesFragmentInteractionListener listener) { mValues = null; mListener = listener; + mPositionalData = new ArrayList<>(); } public void setModules(Modules modules) { mValues = modules; + mPositionalData.clear(); + Semester lastSemester = null; + for (Modules.Module module : mValues) { + Semester semester = module.semester; + if (semester == null) + continue; + if (!semester.equals(lastSemester)) { + mPositionalData.add(new Pair<>(TYPE_HEADER, semester)); + lastSemester = semester; + } + mPositionalData.add(new Pair<>(TYPE_ITEM, module)); + } this.notifyDataSetChanged(); } + @Override + public int getItemViewType(int position) { + return mPositionalData.get(position).first; + } + @NonNull @Override - public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.list_all_items, parent, false); - return new ItemViewHolder(view); + public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == TYPE_HEADER) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_all_caption, parent, false); + return new StringViewHolder(view); + } else { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_all_items, parent, false); + return new ItemViewHolder(view); + } } @Override - public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) { - if (mValues == null) - return; - Modules.Module module = mValues.getByIndex(holder.getAdapterPosition()); - holder.mTitle.setText(module.title); - holder.mSubLeft.setText(module.semester); - holder.mSubRight.setText(module.type); - - holder.mView.setOnClickListener(v -> { - if (null != mListener) { - // Notify the active callbacks interface (the activity, if the - // fragment is attached to one) that an item has been selected. - mListener.onModulesFragmentInteraction(module.getID()); + public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) { + Pair pair = mPositionalData.get(holder.getAdapterPosition()); + if (pair.first == TYPE_HEADER) { + StringViewHolder sHolder = (StringViewHolder) holder; + String localizedSemester; + Semester semester = (Semester) pair.second; + if (semester.getType() == Semester.SEM_WS) + localizedSemester = holder.mView.getResources().getString(R.string.winter_semester, semester.getYear(), semester.getYear()+1); + else + localizedSemester = holder.mView.getResources().getString(R.string.summer_semester, semester.getYear()); + sHolder.mString.setText(localizedSemester); + } else if (pair.first == TYPE_ITEM) { + ItemViewHolder iHolder = (ItemViewHolder) holder; + Modules.Module module = ((Modules.Module) pair.second); + iHolder.mTitle.setText(module.title); + StringBuilder lecturers = new StringBuilder(); + for (Lecturer lecturer : module.lecturer) { + if (!lecturer.isResponsible()) + continue; + if (lecturers.length() > 0) + lecturers.append(", "); + lecturers.append(lecturer.getNameShort()); } - }); + iHolder.mSubLeft.setText(lecturers); + iHolder.mSubRight.setText(module.type); + + iHolder.mView.setOnClickListener(v -> { + if (mListener != null) { + mListener.onModulesFragmentInteraction(module.getID()); + } + }); + } } @Override public int getItemCount() { - if (mValues != null) { - return mValues.size(); - } - return 0; + return mPositionalData.size(); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java index bd98552..5af11f7 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java @@ -14,6 +14,7 @@ import java.util.regex.MatchResult; import de.sebse.fuplanner.services.KVV.types.Lecturer; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Semester; import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.network.HTTPService; @@ -157,7 +158,8 @@ public class ModulesList extends HTTPService { for (int i = 0; i < sites.length(); i++) { try { JSONObject site = sites.getJSONObject(i); - String semester = site.getJSONObject("props").optString("term_eid", null); + String semester_string = site.getJSONObject("props").optString("term_eid", null); + Semester semester = new Semester(semester_string); HashSet lvNumbers = new HashSet<>(); String kvv_lvnumbers = site.getJSONObject("props").optString("kvv_lvnumbers", null); if (kvv_lvnumbers != null) for (MatchResult matchResult : Regex.allMatches("[0-9]+", kvv_lvnumbers)) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java index bad72f5..c84737a 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java @@ -4,13 +4,16 @@ import java.io.Serializable; import java.util.regex.Matcher; import java.util.regex.Pattern; +import de.sebse.fuplanner.tools.logging.Logger; + public class Lecturer implements Serializable { private final String firstName; private final String surname; private final String mail; + private final boolean isResponsible; public Lecturer(String parsableString) throws NoSuchFieldException { - Pattern pattern = Pattern.compile("([^|]*)\\|([^|]*)\\|([^|]*)\\|\\|", Pattern.DOTALL); + Pattern pattern = Pattern.compile("([^|]*)\\|([^|]*)\\|([^|]*)\\|\\|([^|]*)", Pattern.DOTALL); Matcher matcher = pattern.matcher(parsableString); if (!matcher.find()) { throw new NoSuchFieldException(); @@ -18,20 +21,33 @@ public class Lecturer implements Serializable { this.firstName = matcher.group(1); this.surname = matcher.group(2); this.mail = matcher.group(3); + this.isResponsible = matcher.group(4).equals("true"); } - private String getFirstName() { + public String getFirstName() { return firstName; } - private String getSurname() { + public String getSurname() { return surname; } - private String getMail() { + public String getMail() { return mail; } + public boolean isResponsible() { + return isResponsible; + } + + public String getName() { + return getFirstName() + " " + getSurname(); + } + + public String getNameShort() { + return getFirstName().substring(0, 1) + ". " + getSurname(); + } + @Override public String toString() { return "First name: "+ getFirstName()+ diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java index 3d96419..1b87e7d 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.nio.channels.SeekableByteChannel; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; @@ -32,7 +33,7 @@ public class Modules implements Iterable, Serializable { this.list = new SortedListModule(); } - public void addModule(@Nullable String semester, HashSet lvNumber, String title, HashSet lecturer, String type, String description, String ID) { + public void addModule(@Nullable Semester semester, HashSet lvNumber, String title, HashSet lecturer, String type, String description, String ID) { Module m = new Module(semester, lvNumber, title, lecturer, type, description, ID); this.list.add(m); } @@ -109,10 +110,11 @@ public class Modules implements Iterable, Serializable { } public class Module implements Serializable { - @Nullable public final String semester; + @Nullable public final Semester semester; @NotNull final HashSet lvNumber; @NotNull public final String title; - @NotNull final HashSet lecturer; + @NotNull + public final HashSet lecturer; @Nullable public final String type; @Nullable public final String description; @NotNull private final String ID; @@ -136,11 +138,8 @@ public class Modules implements Iterable, Serializable { return userPoint/maxPoint; } - private Module(@Nullable String semester, @NotNull HashSet lvNumber, @NotNull String title, @NotNull HashSet lecturer, @Nullable String type, @Nullable String description, @NotNull String ID) { - if (semester != null) { - semester = semester.replace("SS", "S"); - semester = semester.replaceAll("[0-9]{2}([0-9]{2})", "$1"); - } + private Module(@Nullable Semester semester, @NotNull HashSet lvNumber, @NotNull String title, @NotNull HashSet lecturer, @Nullable String type, @Nullable String description, @NotNull String ID) { + title = title.replaceAll("(.*?) (S[0-9]{2}|W[0-9/]{5})", "$1"); this.semester = semester; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java new file mode 100644 index 0000000..1e81d70 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java @@ -0,0 +1,53 @@ +package de.sebse.fuplanner.services.KVV.types; + +import androidx.annotation.Nullable; +import de.sebse.fuplanner.tools.Regex; + +public class Semester { + public static final int SEM_WS = 1; + public static final int SEM_SS = 2; + private int type; + private int year; + + public Semester(int type, int year) { + this.type = type; + this.year = year; + } + + public Semester(String semester_string) throws NoSuchFieldException { + /*Semester sem = null; + if (semester != null) { + sem = new Semester(semester) + semester = semester.replace("SS", "S"); + semester = semester.replaceAll("[0-9]{2}([0-9]{2})", "$1"); + }*/ + + + /*String s1type = Regex.regex("^(S|WS) ", a); + int s1year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", a, 2)); + String s2type = Regex.regex("^(S|WS) ", b); + int s2year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", b, 2));*/ + + String type = Regex.regex("^(SS|WS) ", semester_string); + String year = Regex.regex("^(SS|WS) ([0-9]{2})", semester_string, 2); + this.type = type.equals("SS") ? SEM_SS : SEM_WS; + this.year = Integer.parseInt(year); + } + + public int getType() { + return type; + } + + public int getYear() { + return year; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof Semester) { + Semester other = (Semester) obj; + return other.type == type && other.year == year; + } + return false; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java index bf306a5..b3b480e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java @@ -1,9 +1,10 @@ package de.sebse.fuplanner.services.KVV.types; +import androidx.annotation.Nullable; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.SortedList; -public class SortedListModule extends SortedList { +public class SortedListModule extends SortedList { private static final int LARGER = 1; private static final int EQUAL = 0; private static final int SMALLER = -1; @@ -27,7 +28,7 @@ public class SortedListModule extends SortedList super.add(e); } - public String getLatestSemester() { + public Semester getLatestSemester() { if (size() > 0) //noinspection ConstantConditions return this.get(0).semester; @@ -35,7 +36,7 @@ public class SortedListModule extends SortedList return null; } - private static int compareSemester(String a, String b) throws NoSuchFieldException { + private static int compareSemester(@Nullable Semester a, @Nullable Semester b) throws NoSuchFieldException { if (a == null && b == null) return EQUAL; if (a == null) @@ -43,17 +44,13 @@ public class SortedListModule extends SortedList if (b == null) return LARGER; - String s1type = Regex.regex("^(S|WS) ", a); - int s1year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", a, 2)); - String s2type = Regex.regex("^(S|WS) ", b); - int s2year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", b, 2)); - if (s1year == s2year) { - if (s1type.equals(s2type)) + if (a.getYear() == b.getYear()) { + if (a.getType() == b.getType()) return EQUAL; - return s1type.equals("S") ? SMALLER : LARGER; + return a.getType() == Semester.SEM_SS ? SMALLER : LARGER; } - return s1year < s2year ? SMALLER : LARGER; + return a.getYear() < b.getYear() ? SMALLER : LARGER; } @Override @@ -62,7 +59,7 @@ public class SortedListModule extends SortedList } @Override - public boolean hasFilter(Modules.Module o1, String filter) { + public boolean hasFilter(Modules.Module o1, Semester filter) { return o1.semester != null && o1.semester.equals(filter); } } diff --git a/app/src/main/res/layout/list_all_items.xml b/app/src/main/res/layout/list_all_items.xml index 05fa9b9..09d8e47 100644 --- a/app/src/main/res/layout/list_all_items.xml +++ b/app/src/main/res/layout/list_all_items.xml @@ -1,51 +1,56 @@ - - - + + android:orientation="horizontal" + android:padding="5dip" > + - + - + - - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4221c85..01149c9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -76,4 +76,6 @@ Klausur Andere Abgabe + Wintersemester %1$d/%2$d + Sommersemester %1$d \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5500875..289dce6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,4 +84,6 @@ Exam Other Deadline + Winter Semester %1$d/%2$d + Summer Semester %1$d