Changed to data classes, and added immutability (#5905)

Co-authored-by: Jinniu Du <127721018+Donutcheese@users.noreply.github.com>
This commit is contained in:
u7479759 2024-11-21 23:42:54 +11:00 committed by GitHub
parent cf88f9b796
commit 088dd2479e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 104 additions and 153 deletions

View file

@ -1,104 +1,45 @@
package fr.free.nrw.commons.profile.achievements
/**
* Represents Achievements class and stores all the parameters
* Represents Achievements data class and stores all the parameters.
* Immutable version with default values for optional properties.
*/
class Achievements {
data class Achievements(
val uniqueUsedImages: Int = 0,
val articlesUsingImages: Int = 0,
val thanksReceived: Int = 0,
val featuredImages: Int = 0,
val qualityImages: Int = 0,
val imagesUploaded: Int = 0,
val revertCount: Int = 0
) {
/**
* The count of unique images used by the wiki.
* @return The count of unique images used.
* @param uniqueUsedImages The count to set for unique images used.
*/
var uniqueUsedImages = 0
private var articlesUsingImages = 0
/**
* The count of thanks received.
* @return The count of thanks received.
* @param thanksReceived The count to set for thanks received.
*/
var thanksReceived = 0
/**
* The count of featured images.
* @return The count of featured images.
* @param featuredImages The count to set for featured images.
*/
var featuredImages = 0
/**
* The count of quality images.
* @return The count of quality images.
* @param qualityImages The count to set for quality images.
*/
var qualityImages = 0
/**
* The count of images uploaded.
* @return The count of images uploaded.
* @param imagesUploaded The count to set for images uploaded.
*/
var imagesUploaded = 0
private var revertCount = 0
constructor() {}
/**
* constructor for achievements class to set its data members
* @param uniqueUsedImages
* @param articlesUsingImages
* @param thanksReceived
* @param featuredImages
* @param imagesUploaded
* @param revertCount
*/
constructor(
uniqueUsedImages: Int,
articlesUsingImages: Int,
thanksReceived: Int,
featuredImages: Int,
qualityImages: Int,
imagesUploaded: Int,
revertCount: Int,
) {
this.uniqueUsedImages = uniqueUsedImages
this.articlesUsingImages = articlesUsingImages
this.thanksReceived = thanksReceived
this.featuredImages = featuredImages
this.qualityImages = qualityImages
this.imagesUploaded = imagesUploaded
this.revertCount = revertCount
}
/**
* used to calculate the percentages of images that haven't been reverted
* @return
* Used to calculate the percentages of images that haven't been reverted.
* Returns 100 if imagesUploaded is 0 to avoid division by zero.
*/
val notRevertPercentage: Int
get() =
try {
(imagesUploaded - revertCount) * 100 / imagesUploaded
} catch (divideByZero: ArithmeticException) {
100
}
get() = if (imagesUploaded > 0) {
(imagesUploaded - revertCount) * 100 / imagesUploaded
} else {
100
}
companion object {
/**
* Get Achievements object from FeedbackResponse
* Get Achievements object from FeedbackResponse.
*
* @param response
* @return
* @param response The feedback response to convert.
* @return An Achievements object with values from the response.
*/
@JvmStatic
fun from(response: FeedbackResponse): Achievements =
Achievements(
response.uniqueUsedImages,
response.articlesUsingImages,
response.thanksReceived,
response.featuredImages.featuredPicturesOnWikimediaCommons,
response.featuredImages.qualityImages,
0,
response.deletedUploads,
)
fun from(response: FeedbackResponse): Achievements = Achievements(
uniqueUsedImages = response.uniqueUsedImages,
articlesUsingImages = response.articlesUsingImages,
thanksReceived = response.thanksReceived,
featuredImages = response.featuredImages.featuredPicturesOnWikimediaCommons,
qualityImages = response.featuredImages.qualityImages,
imagesUploaded = 0, // Assuming imagesUploaded should be 0
revertCount = response.deletedUploads
)
}
}
}

View file

@ -105,7 +105,7 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
// Used for the setting the size of imageView at runtime
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams)
binding.achievementBadgeImage.getLayoutParams();
binding.achievementBadgeImage.getLayoutParams();
params.height = (int) (height * BADGE_IMAGE_HEIGHT_RATIO);
params.width = (int) (width * BADGE_IMAGE_WIDTH_RATIO);
binding.achievementBadgeImage.requestLayout();
@ -186,37 +186,37 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
try{
compositeDisposable.add(okHttpJsonApiClient
.getAchievements(Objects.requireNonNull(userName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
if (response != null) {
setUploadCount(Achievements.from(response));
} else {
Timber.d("success");
binding.layoutImageReverts.setVisibility(View.INVISIBLE);
binding.achievementBadgeImage.setVisibility(View.INVISIBLE);
// If the number of edits made by the user are more than 150,000
// in some cases such high number of wiki edit counts cause the
// achievements calculator to fail in some cases, for more details
// refer Issue: #3295
if (numberOfEdits <= 150000) {
showSnackBarWithRetry(false);
} else {
showSnackBarWithRetry(true);
}
}
},
t -> {
Timber.e(t, "Fetching achievements statistics failed");
if (numberOfEdits <= 150000) {
showSnackBarWithRetry(false);
} else {
showSnackBarWithRetry(true);
}
.getAchievements(Objects.requireNonNull(userName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
if (response != null) {
setUploadCount(Achievements.from(response));
} else {
Timber.d("success");
binding.layoutImageReverts.setVisibility(View.INVISIBLE);
binding.achievementBadgeImage.setVisibility(View.INVISIBLE);
// If the number of edits made by the user are more than 150,000
// in some cases such high number of wiki edit counts cause the
// achievements calculator to fail in some cases, for more details
// refer Issue: #3295
if (numberOfEdits <= 150000) {
showSnackBarWithRetry(false);
} else {
showSnackBarWithRetry(true);
}
));
}
},
t -> {
Timber.e(t, "Fetching achievements statistics failed");
if (numberOfEdits <= 150000) {
showSnackBarWithRetry(false);
} else {
showSnackBarWithRetry(true);
}
}
));
}
catch (Exception e){
Timber.d(e+"success");
@ -233,15 +233,15 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
return;
}
compositeDisposable.add(okHttpJsonApiClient
.getWikidataEdits(userName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(edits -> {
numberOfEdits = edits;
binding.wikidataEdits.setText(String.valueOf(edits));
}, e -> {
Timber.e("Error:" + e);
}));
.getWikidataEdits(userName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(edits -> {
numberOfEdits = edits;
binding.wikidataEdits.setText(String.valueOf(edits));
}, e -> {
Timber.e("Error:" + e);
}));
}
/**
@ -255,11 +255,11 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
if (tooManyAchievements) {
binding.progressBar.setVisibility(View.GONE);
ViewUtil.showDismissibleSnackBar(getActivity().findViewById(android.R.id.content),
R.string.achievements_fetch_failed_ultimate_achievement, R.string.retry, view -> setAchievements());
R.string.achievements_fetch_failed_ultimate_achievement, R.string.retry, view -> setAchievements());
} else {
binding.progressBar.setVisibility(View.GONE);
ViewUtil.showDismissibleSnackBar(getActivity().findViewById(android.R.id.content),
R.string.achievements_fetch_failed, R.string.retry, view -> setAchievements());
R.string.achievements_fetch_failed, R.string.retry, view -> setAchievements());
}
}
@ -277,16 +277,16 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
private void setUploadCount(Achievements achievements) {
if (checkAccount()) {
compositeDisposable.add(okHttpJsonApiClient
.getUploadCount(Objects.requireNonNull(userName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
uploadCount -> setAchievementsUploadCount(achievements, uploadCount),
t -> {
Timber.e(t, "Fetching upload count failed");
onError();
}
));
.getUploadCount(Objects.requireNonNull(userName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
uploadCount -> setAchievementsUploadCount(achievements, uploadCount),
t -> {
Timber.e(t, "Fetching upload count failed");
onError();
}
));
}
}
@ -295,8 +295,18 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
* @param uploadCount
*/
private void setAchievementsUploadCount(Achievements achievements, int uploadCount) {
achievements.setImagesUploaded(uploadCount);
hideProgressBar(achievements);
// Create a new instance of Achievements with updated imagesUploaded
Achievements updatedAchievements = new Achievements(
achievements.getUniqueUsedImages(),
achievements.getArticlesUsingImages(),
achievements.getThanksReceived(),
achievements.getFeaturedImages(),
achievements.getQualityImages(),
uploadCount, // Update imagesUploaded with new value
achievements.getRevertCount()
);
hideProgressBar(updatedAchievements);
}
/**
@ -309,7 +319,7 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
}else {
binding.imagesUploadedProgressbar.setVisibility(View.VISIBLE);
binding.imagesUploadedProgressbar.setProgress
(100*uploadCount/levelInfo.getMaxUploadCount());
(100*uploadCount/levelInfo.getMaxUploadCount());
binding.tvUploadedImages.setText
(uploadCount + "/" + levelInfo.getMaxUploadCount());
}
@ -318,8 +328,8 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
private void setZeroAchievements() {
String message = !Objects.equals(sessionManager.getUserName(), userName) ?
getString(R.string.no_achievements_yet, userName) :
getString(R.string.you_have_no_achievements_yet);
getString(R.string.no_achievements_yet, userName) :
getString(R.string.you_have_no_achievements_yet);
DialogUtil.showAlertDialog(getActivity(),
null,
message,
@ -357,7 +367,7 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
// binding.imagesUsedByWikiProgressBar.setVisibility(View.VISIBLE);
binding.thanksReceived.setText(String.valueOf(achievements.getThanksReceived()));
binding.imagesUsedByWikiProgressBar.setProgress
(100 * achievements.getUniqueUsedImages() / levelInfo.getMaxUniqueImages());
(100 * achievements.getUniqueUsedImages() / levelInfo.getMaxUniqueImages());
binding.tvWikiPb.setText(achievements.getUniqueUsedImages() + "/"
+ levelInfo.getMaxUniqueImages());
binding.imageFeatured.setText(String.valueOf(achievements.getFeaturedImages()));
@ -366,7 +376,7 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
levelUpInfoString += " " + levelInfo.getLevelNumber();
binding.achievementLevel.setText(levelUpInfoString);
binding.achievementBadgeImage.setImageDrawable(VectorDrawableCompat.create(getResources(), R.drawable.badge,
new ContextThemeWrapper(getActivity(), levelInfo.getLevelStyle()).getTheme()));
new ContextThemeWrapper(getActivity(), levelInfo.getLevelStyle()).getTheme()));
binding.achievementBadgeText.setText(Integer.toString(levelInfo.getLevelNumber()));
BasicKvStore store = new BasicKvStore(this.getContext(), userName);
store.putString("userAchievementsLevel", Integer.toString(levelInfo.getLevelNumber()));
@ -378,8 +388,8 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
private void hideProgressBar(Achievements achievements) {
if (binding.progressBar != null) {
levelInfo = LevelController.LevelInfo.from(achievements.getImagesUploaded(),
achievements.getUniqueUsedImages(),
achievements.getNotRevertPercentage());
achievements.getUniqueUsedImages(),
achievements.getNotRevertPercentage());
inflateAchievements(achievements);
setUploadProgress(achievements.getImagesUploaded());
setImageRevertPercentage(achievements.getNotRevertPercentage());
@ -479,4 +489,4 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
}
return true;
}
}
}

View file

@ -6,7 +6,7 @@ import com.google.gson.annotations.SerializedName
* Represents Featured Images on WikiMedia Commons platform
* Used by Achievements and FeedbackResponse (objects) of the user
*/
class FeaturedImages(
data class FeaturedImages(
@field:SerializedName("Quality_images") val qualityImages: Int,
@field:SerializedName("Featured_pictures_on_Wikimedia_Commons") val featuredPicturesOnWikimediaCommons: Int,
)