Skip to content

Commit fa4fd26

Browse files
committed
1.50.3
1 parent 11fe52a commit fa4fd26

File tree

5 files changed

+94
-23
lines changed

5 files changed

+94
-23
lines changed

assets/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: craftserversetup
2-
Version: 1.50.2
2+
Version: 1.50.3
33
Maintainer: Enderbyte Programs <[email protected]>
44
Homepage: https://github.com/Enderbyte-Programs/CraftServerSetup
55
Architecture: all

changelog

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
1.50.1:
1+
1.50.3:
2+
- Add data zooming to the Analytics Viewer
3+
1.50.2:
24
- Improve UUID algorthm
35
- Remove redundant log entry sorting
46
1.50.1:

src/craftserversetup.py

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
VERSION_MANIFEST = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json"
55
BUNGEECORD_DOWNLOAD_URL = "https://ci.md-5.net/job/BungeeCord/lastStableBuild/artifact/bootstrap/target/BungeeCord.jar"
66
APP_VERSION = 1#The API Version.
7-
APP_UF_VERSION = "1.50.2"
7+
APP_UF_VERSION = "1.50.3"
88
#The semver version
99
UPDATEINSTALLED = False
1010
DOCFILE = "https://github.com/Enderbyte-Programs/CraftServerSetup/raw/main/doc/craftserversetup.epdoc"
@@ -2917,6 +2917,7 @@ def __init__(self,lowerdata:LogEntry):
29172917
class ServerMinuteFrame:
29182918
minuteid:int
29192919
onlineplayers:list[str] = []
2920+
playerminutes:int = None
29202921

29212922
def __init__(self,minuteid):
29222923
self.minuteid = minuteid
@@ -2926,6 +2927,11 @@ def todatetime(self) -> datetime:
29262927
return datetime.datetime.fromtimestamp(self.minuteid*60)
29272928
def howmanyonline(self) -> int:
29282929
return len(self.onlineplayers)
2930+
def getplayerminutes(self) -> int:
2931+
if self.playerminutes is None:
2932+
return self.howmanyonline()
2933+
else:
2934+
return self.playerminutes
29292935

29302936
def serverminuteframe_uf(smf:ServerMinuteFrame):
29312937
return f"{smf.minuteid} ({smf.todatetime()}) - {smf.onlineplayers}"
@@ -2950,27 +2956,46 @@ def split_list_into_chunks(l, n):
29502956
yield l[i:i + n]
29512957

29522958
class AnalyticsExplorerZoomLevels(enum.Enum):
2953-
MINUTE = 0
2959+
MINUTE = 1
29542960
HOUR = 60
29552961
DAY = 1440
2956-
MONTH = 43200
2962+
WEEK = 1440*7
29572963

29582964
class AnalyticsExplorerDataTypes(enum.Enum):
29592965
TOTALPLAYERMINUTES = 0
2960-
MAXPLAYERCOUNT = 1
2961-
AVERAGEPLAYERCOUNT = 2
2966+
PLAYERCOUNT = 1
29622967

29632968
def sort_dict_by_key(d:dict) -> dict:
29642969
return dict(sorted(list(d.items())))
29652970

2971+
def get_chunk_size_from_aezl(s:AnalyticsExplorerZoomLevels):
2972+
return {
2973+
AnalyticsExplorerZoomLevels.MINUTE:1,
2974+
AnalyticsExplorerZoomLevels.HOUR:60,
2975+
AnalyticsExplorerZoomLevels.DAY:1440,
2976+
AnalyticsExplorerZoomLevels.WEEK:1440*7
2977+
}[s]
2978+
29662979
def server_analytics_explorer(stdscr,data:dict[int,ServerMinuteFrame]):
2967-
2980+
cursesplus.displaymsg(stdscr,["Analytics Explorer","Initializing..."],False)
29682981
#This function allows users to explore their analytics
29692982
offset = 0
29702983
datasize = len(data)-1
29712984
currentzoomlevel = AnalyticsExplorerZoomLevels.MINUTE#Also passively the list chunk size
2972-
currentdatatype = AnalyticsExplorerDataTypes.MAXPLAYERCOUNT
2985+
currentdatatype = AnalyticsExplorerDataTypes.PLAYERCOUNT
2986+
zoomlevels = {
2987+
AnalyticsExplorerZoomLevels.MINUTE: "Minute (default)",
2988+
AnalyticsExplorerZoomLevels.HOUR: "Hour",
2989+
AnalyticsExplorerZoomLevels.DAY: "Day",
2990+
AnalyticsExplorerZoomLevels.WEEK: "Week"
2991+
}
2992+
datatypes = {
2993+
AnalyticsExplorerDataTypes.TOTALPLAYERMINUTES: "Player Minutes Spent",
2994+
AnalyticsExplorerDataTypes.PLAYERCOUNT: "Online Players (default)"
2995+
}
29732996
ldata = list(data.values())#List representation of data to prevent performance issues?
2997+
ogdata = copy.deepcopy(data)
2998+
ogldata = copy.deepcopy(ldata)#For use later
29742999
maxval = max([len(p.onlineplayers) for p in list(data.values())])
29753000
while True:
29763001
my,mx = stdscr.getmaxyx()
@@ -2980,8 +3005,6 @@ def server_analytics_explorer(stdscr,data:dict[int,ServerMinuteFrame]):
29803005
cursesplus.utils.fill_line(stdscr,0,cursesplus.set_colour(cursesplus.BLUE,cursesplus.BLUE))
29813006
stdscr.addstr(0,0,"Analytics Explorer - Press Q to quit and H for help",cursesplus.set_colour(cursesplus.BLUE,cursesplus.WHITE))
29823007

2983-
if currentdatatype == AnalyticsExplorerDataTypes.TOTALPLAYERMINUTES:
2984-
maxval = maxval*currentzoomlevel
29853008

29863009
ti = 0
29873010
for i in range(offset-xspace//2,offset+xspace//2):
@@ -2992,7 +3015,10 @@ def server_analytics_explorer(stdscr,data:dict[int,ServerMinuteFrame]):
29923015
stdscr.addstr(dy,ti,"█",cursesplus.set_colour(cursesplus.RED,cursesplus.RED))
29933016
else:
29943017
seldata = ldata[i]
2995-
scale = int(seldata.howmanyonline()/maxval*yspace)
3018+
if currentdatatype == AnalyticsExplorerDataTypes.PLAYERCOUNT:
3019+
scale = int(seldata.howmanyonline()/maxval*yspace)
3020+
else:
3021+
scale = int(seldata.getplayerminutes()/maxval*yspace)
29963022

29973023
if i == offset:
29983024
for p in range(1,yspace+2):
@@ -3006,13 +3032,19 @@ def server_analytics_explorer(stdscr,data:dict[int,ServerMinuteFrame]):
30063032
ti += 1
30073033

30083034
seldata = ldata[offset]
3009-
stdscr.addstr(my-2,0,f"{strip_datetime(get_datetime_from_minute_id(seldata.minuteid))} || {seldata.howmanyonline()} players online - {seldata.onlineplayers}")
3035+
if currentdatatype == AnalyticsExplorerDataTypes.TOTALPLAYERMINUTES:
3036+
stdscr.addstr(my-2,0,f"{strip_datetime(get_datetime_from_minute_id(seldata.minuteid))} || {seldata.getplayerminutes()} player-minutes")
3037+
else:
3038+
try:
3039+
stdscr.addstr(my-2,0,f"{strip_datetime(get_datetime_from_minute_id(seldata.minuteid))} || {seldata.howmanyonline()} players online - {seldata.onlineplayers}")
3040+
except:
3041+
stdscr.addstr(my-2,0,f"{strip_datetime(get_datetime_from_minute_id(seldata.minuteid))} || {seldata.howmanyonline()} players online")#Too long for list
30103042

30113043
ch = curses.keyname(stdscr.getch()).decode()
30123044
if ch == "q":
30133045
break
30143046
elif ch == "h":
3015-
cursesplus.displaymsg(stdscr,["KEYBINDS","q - Quit","h - Help","<- -> Scroll","END - Go to end","HOME - Go to beginning","j - Jump to time","SHIFT <-- --> - Jump hour","Ctrl <-- --> - Jump day"])
3047+
cursesplus.displaymsg(stdscr,["KEYBINDS","q - Quit","h - Help","<- -> Scroll","END - Go to end","HOME - Go to beginning","j - Jump to time","SHIFT <-- --> - Jump hour","Ctrl <-- --> - Jump day","T - Select time unit","D - Select data type"])
30163048
elif ch == "KEY_LEFT":
30173049
if offset > 0:
30183050
offset -= 1
@@ -3025,9 +3057,9 @@ def server_analytics_explorer(stdscr,data:dict[int,ServerMinuteFrame]):
30253057
offset = 0
30263058
elif ch == "KEY_SRIGHT":#Jump around by an hour
30273059
offset += 60
3028-
elif ch == "kRIT5":
3060+
elif ch == "kRIT5":#ctrl left
30293061
offset += 1440
3030-
elif ch == "kLFT5":
3062+
elif ch == "kLFT5":#ctrl right
30313063
if offset > 1440:
30323064
offset -= 1440
30333065
else:
@@ -3039,11 +3071,52 @@ def server_analytics_explorer(stdscr,data:dict[int,ServerMinuteFrame]):
30393071
elif ch == "j":
30403072
stdscr.clear()
30413073
ndate = cursesplus.date_time_selector(stdscr,cursesplus.DateTimeSelectorTypes.DATEANDTIME,"Choose a date and time to jump to",True,False,get_datetime_from_minute_id(ldata[offset].minuteid))
3074+
if currentzoomlevel == AnalyticsExplorerZoomLevels.HOUR:
3075+
ndate.minute = 0
3076+
ndate.second = 0
3077+
if currentzoomlevel == AnalyticsExplorerZoomLevels.DAY or currentzoomlevel == AnalyticsExplorerZoomLevels.WEEK:
3078+
ndate.hour = 0
30423079
nmid = get_minute_id_from_datetime(ndate)
30433080
if not nmid in data:
30443081
cursesplus.messagebox.showerror(stdscr,["Records do not exist for the selected date."])
30453082
else:
30463083
offset = list(data.keys()).index(nmid)
3084+
elif ch == "t":
3085+
currentzoomlevel = list(zoomlevels.keys())[crss_custom_ad_menu(stdscr,list(zoomlevels.values()),"Choose a zoom level")]
3086+
cursesplus.displaymsg(stdscr,["Generating Data"],False)
3087+
#This will use ogdat because data may have been used for hour or day, which will screw it up
3088+
offset = 0
3089+
if currentzoomlevel == AnalyticsExplorerZoomLevels.MINUTE:
3090+
data = ogdata
3091+
ldata = ogldata
3092+
else:
3093+
chunked_data:list[list[ServerMinuteFrame]] = split_list_into_chunks(ogldata,get_chunk_size_from_aezl(currentzoomlevel))
3094+
final_data:dict[int,ServerMinuteFrame] = {}
3095+
for chunk in chunked_data:
3096+
s:ServerMinuteFrame = ServerMinuteFrame(chunk[0].minuteid)
3097+
#Append all unique players, and set playerminutes
3098+
total_playerminutes = 0
3099+
unique_players = []
3100+
for minute in chunk:
3101+
total_playerminutes += minute.howmanyonline()
3102+
for onlineplayer in minute.onlineplayers:
3103+
if onlineplayer not in unique_players:
3104+
unique_players.append(onlineplayer)
3105+
s.playerminutes = total_playerminutes
3106+
s.onlineplayers = unique_players
3107+
final_data[s.minuteid] = s
3108+
data = final_data
3109+
ldata = list(data.values())
3110+
maxval = max([p.getplayerminutes() for p in list(data.values())])
3111+
#if currentdatatype == AnalyticsExplorerDataTypes.TOTALPLAYERMINUTES:
3112+
# maxval = maxval*get_chunk_size_from_aezl(currentzoomlevel)
3113+
datasize = len(data)-1
3114+
3115+
elif ch == "d":
3116+
currentdatatype = list(datatypes.keys())[crss_custom_ad_menu(stdscr,list(datatypes.values()),"Choose a data type")]
3117+
maxval = max([p.getplayerminutes() for p in list(data.values())])
3118+
#if currentdatatype == AnalyticsExplorerDataTypes.TOTALPLAYERMINUTES:
3119+
# maxval = maxval*get_chunk_size_from_aezl(currentzoomlevel)
30473120
if offset > datasize:
30483121
offset = datasize - 1
30493122

@@ -3082,7 +3155,8 @@ def sanalytics(stdscr,serverdir):
30823155
rs:str = lz[0].strip()
30833156
plname = rs.split(" ")[0]
30843157
action = rs.split(" ")[1]
3085-
3158+
#Remove special characters from plname
3159+
plname = plname.replace("(","")
30863160
mid = get_minute_id_from_datetime(eventslist[-1].ext)
30873161
if "joined" in action:
30883162
if not mid in joins:

todo

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
- Minor fixes:
22
- Releases, Snapshots, and Experiments are sorted into groups in vanilla version selection menu
3-
- Analysis improvement:
4-
- AE data and zoom
5-
- Player:
6-
- View minutes over months
7-
- View minutes over day
83
- Add bungeecord and Velocity support
94
- Add inventory viewer or player data editor
105
- Add disk space analyzer

update.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
https://github.com/Enderbyte-Programs/CraftServerSetup/releases/download/v1.50.2/CraftServerSetup-1.50.2-installer.exe|1.50.2|Add stuff
1+
https://github.com/Enderbyte-Programs/CraftServerSetup/releases/download/v1.50.3/CraftServerSetup-1.50.3-installer.exe|1.50.3|Add stuff

0 commit comments

Comments
 (0)