v1.3.0: implemented rankings support for daily runs
This commit is contained in:
@@ -194,6 +194,21 @@ public class Bundle {
|
||||
}
|
||||
}
|
||||
|
||||
public long[] getLongArray( String key ) {
|
||||
try {
|
||||
JSONArray array = data.getJSONArray( key );
|
||||
int length = array.length();
|
||||
long[] result = new long[length];
|
||||
for (int i=0; i < length; i++) {
|
||||
result[i] = array.getLong( i );
|
||||
}
|
||||
return result;
|
||||
} catch (JSONException e) {
|
||||
Game.reportException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public float[] getFloatArray( String key ) {
|
||||
try {
|
||||
JSONArray array = data.getJSONArray( key );
|
||||
@@ -386,6 +401,18 @@ public class Bundle {
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, long[] array ) {
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i=0; i < array.length; i++) {
|
||||
jsonArray.put( i, array[i] );
|
||||
}
|
||||
data.put( key, jsonArray );
|
||||
} catch (JSONException e) {
|
||||
Game.reportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, float[] array ) {
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
|
||||
@@ -21,6 +21,11 @@ windows.wndclass.mastery=Mastery
|
||||
|
||||
windows.wndcombo.title=choose a combo move
|
||||
|
||||
windows.wnddailies.title=Daily History
|
||||
windows.wnddailies.date=Date
|
||||
windows.wnddailies.score=Score
|
||||
|
||||
|
||||
windows.wnddocument.missing=page missing
|
||||
|
||||
windows.wndenergizeitem.prompt=Energize an Item
|
||||
|
||||
@@ -46,6 +46,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public enum Rankings {
|
||||
@@ -61,16 +62,17 @@ public enum Rankings {
|
||||
public int totalNumber;
|
||||
public int wonNumber;
|
||||
|
||||
//The number of runs which are only present locally, not in the cloud
|
||||
public int localTotal;
|
||||
public int localWon;
|
||||
|
||||
public Record latestDaily;
|
||||
public LinkedHashMap<Long, Integer> dailyScoreHistory = new LinkedHashMap<>();
|
||||
|
||||
public void submit( boolean win, Class cause ) {
|
||||
|
||||
load();
|
||||
|
||||
//TODO need separate storage for daily data
|
||||
//when loading data, make sure to check for latestDaily errors and correct
|
||||
if (Dungeon.daily){
|
||||
return;
|
||||
}
|
||||
|
||||
Record rec = new Record();
|
||||
|
||||
rec.cause = cause;
|
||||
@@ -87,6 +89,7 @@ public enum Rankings {
|
||||
}
|
||||
rec.score = calculateScore();
|
||||
rec.customSeed = Dungeon.customSeedText;
|
||||
rec.daily = Dungeon.daily;
|
||||
|
||||
Badges.validateHighScore( rec.score );
|
||||
|
||||
@@ -94,6 +97,13 @@ public enum Rankings {
|
||||
|
||||
rec.gameID = UUID.randomUUID().toString();
|
||||
|
||||
if (rec.daily){
|
||||
latestDaily = rec;
|
||||
dailyScoreHistory.put(Dungeon.seed, rec.score);
|
||||
save();
|
||||
return;
|
||||
}
|
||||
|
||||
records.add( rec );
|
||||
|
||||
Collections.sort( records, scoreComparator );
|
||||
@@ -308,6 +318,10 @@ public enum Rankings {
|
||||
private static final String TOTAL = "total";
|
||||
private static final String WON = "won";
|
||||
|
||||
public static final String LATEST_DAILY = "latest_daily";
|
||||
public static final String DAILY_HISTORY_DATES = "daily_history_dates";
|
||||
public static final String DAILY_HISTORY_SCORES = "daily_history_scores";
|
||||
|
||||
public void save() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.put( RECORDS, records );
|
||||
@@ -315,6 +329,19 @@ public enum Rankings {
|
||||
bundle.put( TOTAL, totalNumber );
|
||||
bundle.put( WON, wonNumber );
|
||||
|
||||
bundle.put(LATEST_DAILY, latestDaily);
|
||||
|
||||
long[] dates = new long[dailyScoreHistory.size()];
|
||||
int[] scores = new int[dailyScoreHistory.size()];
|
||||
int i = 0;
|
||||
for (Long l : dailyScoreHistory.keySet()){
|
||||
dates[i] = l;
|
||||
scores[i] = dailyScoreHistory.get(l);
|
||||
i++;
|
||||
}
|
||||
bundle.put(DAILY_HISTORY_DATES, dates);
|
||||
bundle.put(DAILY_HISTORY_SCORES, scores);
|
||||
|
||||
try {
|
||||
FileUtils.bundleToFile( RANKINGS_FILE, bundle);
|
||||
} catch (IOException e) {
|
||||
@@ -353,6 +380,23 @@ public enum Rankings {
|
||||
}
|
||||
}
|
||||
|
||||
if (bundle.contains(LATEST_DAILY)){
|
||||
latestDaily = (Record) bundle.get(LATEST_DAILY);
|
||||
|
||||
dailyScoreHistory.clear();
|
||||
int[] scores = bundle.getIntArray(DAILY_HISTORY_SCORES);
|
||||
int i = 0;
|
||||
long latestDate = 0;
|
||||
for (long date : bundle.getLongArray(DAILY_HISTORY_DATES)){
|
||||
dailyScoreHistory.put(date, scores[i]);
|
||||
if (date > latestDate) latestDate = date;
|
||||
i++;
|
||||
}
|
||||
if (latestDate > SPDSettings.lastDaily()){
|
||||
SPDSettings.lastDaily(latestDate);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
@@ -370,6 +414,7 @@ public enum Rankings {
|
||||
private static final String DATA = "gameData";
|
||||
private static final String ID = "gameID";
|
||||
private static final String SEED = "custom_seed";
|
||||
private static final String DAILY = "daily";
|
||||
|
||||
public Class cause;
|
||||
public boolean win;
|
||||
@@ -387,6 +432,7 @@ public enum Rankings {
|
||||
public int score;
|
||||
|
||||
public String customSeed;
|
||||
public boolean daily;
|
||||
|
||||
public String desc(){
|
||||
if (win){
|
||||
@@ -419,6 +465,7 @@ public enum Rankings {
|
||||
win = bundle.getBoolean( WIN );
|
||||
score = bundle.getInt( SCORE );
|
||||
customSeed = bundle.getString( SEED );
|
||||
daily = bundle.getBoolean( DAILY );
|
||||
|
||||
heroClass = bundle.getEnum( CLASS, HeroClass.class );
|
||||
armorTier = bundle.getInt( TIER );
|
||||
@@ -441,6 +488,7 @@ public enum Rankings {
|
||||
bundle.put( WIN, win );
|
||||
bundle.put( SCORE, score );
|
||||
bundle.put( SEED, customSeed );
|
||||
bundle.put( DAILY, daily );
|
||||
|
||||
bundle.put( CLASS, heroClass );
|
||||
bundle.put( TIER, armorTier );
|
||||
@@ -456,6 +504,7 @@ public enum Rankings {
|
||||
public static final Comparator<Record> scoreComparator = new Comparator<Rankings.Record>() {
|
||||
@Override
|
||||
public int compare( Record lhs, Record rhs ) {
|
||||
//this covers custom seeded runs and dailies
|
||||
if (rhs.customSeed.isEmpty() && !lhs.customSeed.isEmpty()){
|
||||
return +1;
|
||||
} else if (lhs.customSeed.isEmpty() && !rhs.customSeed.isEmpty()){
|
||||
|
||||
@@ -31,9 +31,11 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.ExitButton;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndDailies;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndError;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndRanking;
|
||||
import com.watabou.noosa.BitmapText;
|
||||
@@ -139,6 +141,26 @@ public class RankingsScene extends PixelScene {
|
||||
btnExit.setPos( Camera.main.width - btnExit.width(), 0 );
|
||||
add( btnExit );
|
||||
|
||||
int left = 0;
|
||||
|
||||
if (Rankings.INSTANCE.latestDaily != null) {
|
||||
IconButton btnDailies = new IconButton(Icons.CALENDAR.get()) {
|
||||
@Override
|
||||
protected void onClick() {
|
||||
ShatteredPixelDungeon.scene().addToFront(new WndDailies());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPointerUp() {
|
||||
icon.hardlight(0.5f, 1f, 2f);
|
||||
}
|
||||
};
|
||||
btnDailies.icon().hardlight(0.5f, 1f, 2f);
|
||||
btnDailies.setRect( left, 0, 20, 20 );
|
||||
left += 20;
|
||||
add(btnDailies);
|
||||
}
|
||||
|
||||
fadeIn();
|
||||
}
|
||||
|
||||
@@ -158,7 +180,7 @@ public class RankingsScene extends PixelScene {
|
||||
|
||||
private Rankings.Record rec;
|
||||
|
||||
protected ItemSprite shield;
|
||||
protected Image shield;
|
||||
private Flare flare;
|
||||
private BitmapText position;
|
||||
private RenderedTextBlock desc;
|
||||
@@ -190,7 +212,7 @@ public class RankingsScene extends PixelScene {
|
||||
int odd = pos % 2;
|
||||
|
||||
if (rec.win) {
|
||||
shield.view( ItemSpriteSheet.AMULET, null );
|
||||
shield.copy( new ItemSprite(ItemSpriteSheet.AMULET, null) );
|
||||
position.hardlight( TEXT_WIN[odd] );
|
||||
desc.hardlight( TEXT_WIN[odd] );
|
||||
depth.hardlight( TEXT_WIN[odd] );
|
||||
@@ -211,14 +233,18 @@ public class RankingsScene extends PixelScene {
|
||||
}
|
||||
|
||||
if (rec.ascending){
|
||||
shield.view( ItemSpriteSheet.AMULET, null );
|
||||
shield.copy( new ItemSprite(ItemSpriteSheet.AMULET, null) );
|
||||
shield.hardlight(0.4f, 0.4f, 0.7f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!rec.customSeed.isEmpty()){
|
||||
shield.view( ItemSpriteSheet.SEED_SUNGRASS, null );
|
||||
if (rec.daily){
|
||||
shield.copy( Icons.get(Icons.CALENDAR) );
|
||||
shield.hardlight(0.5f, 1f, 2f);
|
||||
} else if (!rec.customSeed.isEmpty()){
|
||||
shield.copy( Icons.get(Icons.SEED) );
|
||||
shield.hardlight(1f, 1.5f, 0.67f);
|
||||
}
|
||||
|
||||
if (rec.herolevel != 0){
|
||||
@@ -239,7 +265,7 @@ public class RankingsScene extends PixelScene {
|
||||
|
||||
super.createChildren();
|
||||
|
||||
shield = new ItemSprite( ItemSpriteSheet.TOMB, null );
|
||||
shield = new Image(new ItemSprite( ItemSpriteSheet.TOMB, null ));
|
||||
add( shield );
|
||||
|
||||
position = new BitmapText( PixelScene.pixelFont);
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2022 Evan Debenham
|
||||
*
|
||||
* 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 com.shatteredpixel.shatteredpixeldungeon.windows;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Rankings;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.IconButton;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
|
||||
import com.watabou.noosa.ColorBlock;
|
||||
import com.watabou.noosa.ui.Component;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class WndDailies extends Window {
|
||||
|
||||
private static final int WIDTH = 115;
|
||||
private static final int HEIGHT = 144;
|
||||
|
||||
public WndDailies(){
|
||||
|
||||
resize(WIDTH, HEIGHT);
|
||||
|
||||
ScrollPane pane = new ScrollPane(new Component());
|
||||
add(pane);
|
||||
pane.setRect(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
Component content = pane.content();
|
||||
|
||||
IconTitle title = new IconTitle(Icons.CALENDAR.get(), Messages.get(this, "title"));
|
||||
title.imIcon.hardlight(0.5f, 1f, 2f);
|
||||
title.setRect(0, 0, WIDTH, 0);
|
||||
title.setPos(0, 0);
|
||||
content.add(title);
|
||||
|
||||
int top = (int)title.bottom()+3;
|
||||
|
||||
RenderedTextBlock day = PixelScene.renderTextBlock(Messages.get(this, "date"), 7);
|
||||
day.hardlight(TITLE_COLOR);
|
||||
day.setPos(0, top);
|
||||
content.add(day);
|
||||
|
||||
RenderedTextBlock score = PixelScene.renderTextBlock(Messages.get(this, "score"), 7);
|
||||
score.hardlight(TITLE_COLOR);
|
||||
score.setPos(WIDTH - score.width(), top);
|
||||
content.add(score);
|
||||
|
||||
top = (int) score.bottom() + 6;
|
||||
|
||||
NumberFormat num = NumberFormat.getInstance(Locale.US);
|
||||
DateFormat format = DateFormat.getDateInstance();
|
||||
format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
Date date = new Date();
|
||||
|
||||
//reverse order so that latest dailies are on top
|
||||
ArrayList<Long> dates = new ArrayList<>(Rankings.INSTANCE.dailyScoreHistory.keySet());
|
||||
Collections.reverse(dates);
|
||||
|
||||
boolean first = Rankings.INSTANCE.latestDaily != null;
|
||||
for (long l : dates) {
|
||||
if (first) top += 2;
|
||||
|
||||
ColorBlock sep = new ColorBlock(WIDTH, 1, 0xFF000000);
|
||||
sep.y = top - 3 - (first ? 2 : 0);
|
||||
content.add(sep);
|
||||
|
||||
date.setTime(l);
|
||||
day = PixelScene.renderTextBlock(format.format(date), 7);
|
||||
day.setPos(0, top);
|
||||
content.add(day);
|
||||
|
||||
if (first){
|
||||
IconButton latestInfo = new IconButton(Icons.INFO.get()){
|
||||
@Override
|
||||
protected void onClick() {
|
||||
ShatteredPixelDungeon.scene().addToFront(new WndRanking(Rankings.INSTANCE.latestDaily));
|
||||
}
|
||||
};
|
||||
latestInfo.setRect(day.right()+2, top - 5, 16, 16);
|
||||
content.add(latestInfo);
|
||||
}
|
||||
|
||||
score = PixelScene.renderTextBlock(num.format(Rankings.INSTANCE.dailyScoreHistory.get(l)), 7);
|
||||
score.setPos(WIDTH - score.width(), top);
|
||||
content.add(score);
|
||||
|
||||
top = (int) day.bottom() + 6;
|
||||
if (first){
|
||||
top += 2;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
content.setRect(0, 0, WIDTH, top);
|
||||
pane.setRect(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -217,9 +217,9 @@ public class WndRanking extends WndTabbed {
|
||||
}
|
||||
if (Dungeon.seed != -1) {
|
||||
if (Dungeon.daily){
|
||||
pos = statSlot(this, Messages.get(this, "daily_for"), "_" + DungeonSeed.convertToCode(Dungeon.seed) + "_", pos);
|
||||
pos = statSlot(this, Messages.get(this, "daily_for"), "_" + Dungeon.customSeedText + "_", pos);
|
||||
} else if (!Dungeon.customSeedText.isEmpty()){
|
||||
pos = statSlot(this, Messages.get(this, "custom_seed"), "_" + DungeonSeed.convertToCode(Dungeon.seed) + "_", pos);
|
||||
pos = statSlot(this, Messages.get(this, "custom_seed"), "_" + Dungeon.customSeedText + "_", pos);
|
||||
} else {
|
||||
pos = statSlot(this, Messages.get(this, "seed"), DungeonSeed.convertToCode(Dungeon.seed), pos);
|
||||
}
|
||||
@@ -236,7 +236,8 @@ public class WndRanking extends WndTabbed {
|
||||
|
||||
int buttontop = HEIGHT - 16;
|
||||
|
||||
if (Dungeon.seed != -1 && (DeviceCompat.isDebug() || Badges.isUnlocked(Badges.Badge.VICTORY))){
|
||||
if (Dungeon.seed != -1 && !Dungeon.daily &&
|
||||
(DeviceCompat.isDebug() || Badges.isUnlocked(Badges.Badge.VICTORY))){
|
||||
final Image icon = Icons.get(Icons.SEED);
|
||||
RedButton btnSeed = new RedButton(Messages.get(this, "copy_seed")){
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user