Made analytics more powerfull
This commit is contained in:
parent
8d12e15f07
commit
beb6d23f85
4 changed files with 273 additions and 59 deletions
|
@ -388,6 +388,23 @@ def draw(outlayer, win, path, back="story_editor"):
|
|||
"settings/themes/"+win.settings["Theme"]+"/icons/checklist.png",
|
||||
5, 5, 40, 40)
|
||||
|
||||
# If not in the analytics window. I want to have a button to go to analyitcs.
|
||||
if win.url != "analytics":
|
||||
reducing = 60
|
||||
def do():
|
||||
win.cur = "/set"
|
||||
win.url = "analytics"
|
||||
UI_elements.roundrect(layer, win,
|
||||
width - 55,
|
||||
5,
|
||||
40,
|
||||
40,
|
||||
10,
|
||||
do,
|
||||
offset=[x,y],
|
||||
icon="analytics")
|
||||
else:
|
||||
reducing = 0
|
||||
# Fraction
|
||||
|
||||
fraction = win.checklists[path]["fraction"]
|
||||
|
@ -396,7 +413,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
|||
UI_elements.roundrect(layer, win,
|
||||
50,
|
||||
17,
|
||||
width - 60,
|
||||
width - 60 -reducing,
|
||||
0,
|
||||
7)
|
||||
|
||||
|
@ -404,7 +421,7 @@ def draw(outlayer, win, path, back="story_editor"):
|
|||
UI_elements.roundrect(layer, win,
|
||||
50,
|
||||
17,
|
||||
(width - 60 )*fraction,
|
||||
(width - 60 -reducing)*fraction,
|
||||
0,
|
||||
7)
|
||||
|
||||
|
|
|
@ -46,8 +46,53 @@ from studio import studio_dialogs
|
|||
from studio import schedule
|
||||
from studio import history
|
||||
|
||||
def datetip(win, date):
|
||||
|
||||
# Function that outputs basic analytics about a given date
|
||||
# in text form
|
||||
|
||||
# TODO: This function is in a prototype stage. Meaning it's
|
||||
# not translated to multiple languages. This should be fixed.
|
||||
# See settings/talk.py file.
|
||||
|
||||
text = date
|
||||
|
||||
try:
|
||||
data = win.analytics["dates"][date]
|
||||
|
||||
# Expected
|
||||
|
||||
startdate = win.analytics["startdate"]
|
||||
deadline = win.analytics["deadline"]
|
||||
duration = win.analytics["duration"]
|
||||
new_date_format = "%Y/%m/%d"
|
||||
sd = datetime.datetime.strptime(startdate, new_date_format)
|
||||
nd = datetime.datetime.strptime(date , new_date_format)
|
||||
|
||||
dn = nd - sd
|
||||
daysin = int(dn.days)
|
||||
|
||||
expected = round(100 / duration * daysin, 2)
|
||||
text = text +"\n\nExpected: "+str(expected)+"%"
|
||||
|
||||
# Actual
|
||||
frac = round(data.get("fractions", {}).get("project")*100, 2)
|
||||
text = text +"\nActual: "+str(frac)+"%"
|
||||
|
||||
# Productivity
|
||||
productivity = int(round(frac - expected+100))
|
||||
text = text +"\n\nProductivity: "+str(productivity)+"%"
|
||||
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def layer(win):
|
||||
|
||||
# This is very important. I makes live easier. LOL.
|
||||
win.current["shot_left_side_scroll_please_work_omg_wtf"] = True
|
||||
|
||||
# Making the layer
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'],
|
||||
|
@ -151,7 +196,9 @@ def layer(win):
|
|||
25,
|
||||
win.current["w"]/2-80,
|
||||
20,
|
||||
10)
|
||||
10,
|
||||
tip=str(round(projectdone*100, 1))+"%")
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -180,7 +227,8 @@ def layer(win):
|
|||
65,
|
||||
win.current["w"]/2-80,
|
||||
20,
|
||||
10)
|
||||
10,
|
||||
tip=str(round(timepassed*100, 1))+"%")
|
||||
|
||||
# Timepassed
|
||||
UI_color.set(layer, win, "progress_time")
|
||||
|
@ -195,22 +243,25 @@ def layer(win):
|
|||
|
||||
# Icon
|
||||
UI_elements.image(layer, win, "settings/themes/"\
|
||||
+win.settings["Theme"]+"/icons/scene.png",
|
||||
+win.settings["Theme"]+"/icons/shot.png",
|
||||
win.current["w"]/4+10,
|
||||
95,
|
||||
40,
|
||||
40)
|
||||
|
||||
UI_color.set(layer, win, "progress_background")
|
||||
UI_color.set(layer, win, "shot_5")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+60,
|
||||
105,
|
||||
win.current["w"]/2-80,
|
||||
20,
|
||||
10)
|
||||
10,
|
||||
tip=str(round(rnddone*100, 1))+"%",
|
||||
fill=False)
|
||||
layer.stroke()
|
||||
|
||||
# Scenes
|
||||
UI_color.set(layer, win, "node_videofile")
|
||||
UI_color.set(layer, win, "shot_5")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+60,
|
||||
105,
|
||||
|
@ -228,16 +279,19 @@ def layer(win):
|
|||
40,
|
||||
40)
|
||||
|
||||
UI_color.set(layer, win, "progress_background")
|
||||
UI_color.set(layer, win, "shot_1")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+60,
|
||||
145,
|
||||
win.current["w"]/4-80,
|
||||
20,
|
||||
10)
|
||||
10,
|
||||
tip=str(round(chrdone*100, 1))+"%",
|
||||
fill=False)
|
||||
layer.stroke()
|
||||
|
||||
# progress
|
||||
UI_color.set(layer, win, "node_asset")
|
||||
UI_color.set(layer, win, "shot_1")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+60,
|
||||
145,
|
||||
|
@ -255,16 +309,19 @@ def layer(win):
|
|||
40,
|
||||
40)
|
||||
|
||||
UI_color.set(layer, win, "progress_background")
|
||||
UI_color.set(layer, win, "shot_2")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/2+60,
|
||||
145,
|
||||
win.current["w"]/4-80,
|
||||
20,
|
||||
10)
|
||||
10,
|
||||
tip=str(round(vehdone*100, 1))+"%",
|
||||
fill=False)
|
||||
layer.stroke()
|
||||
|
||||
# progress
|
||||
UI_color.set(layer, win, "node_imagefile")
|
||||
UI_color.set(layer, win, "shot_2")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/2+60,
|
||||
145,
|
||||
|
@ -282,16 +339,19 @@ def layer(win):
|
|||
40,
|
||||
40)
|
||||
|
||||
UI_color.set(layer, win, "progress_background")
|
||||
UI_color.set(layer, win, "shot_3")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+60,
|
||||
185,
|
||||
win.current["w"]/4-80,
|
||||
20,
|
||||
10)
|
||||
10,
|
||||
tip=str(round(locdone*100, 1))+"%",
|
||||
fill=False)
|
||||
layer.stroke()
|
||||
|
||||
# progress
|
||||
UI_color.set(layer, win, "node_blendfile")
|
||||
UI_color.set(layer, win, "shot_3")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+60,
|
||||
185,
|
||||
|
@ -309,16 +369,19 @@ def layer(win):
|
|||
40,
|
||||
40)
|
||||
|
||||
UI_color.set(layer, win, "progress_background")
|
||||
UI_color.set(layer, win, "shot_4")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/2+60,
|
||||
185,
|
||||
win.current["w"]/4-80,
|
||||
20,
|
||||
10)
|
||||
10,
|
||||
tip=str(round(objdone*100, 1))+"%",
|
||||
fill=False)
|
||||
layer.stroke()
|
||||
|
||||
# progress
|
||||
UI_color.set(layer, win, "node_badfile")
|
||||
UI_color.set(layer, win, "shot_4")
|
||||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/2+60,
|
||||
185,
|
||||
|
@ -347,7 +410,7 @@ def layer(win):
|
|||
# Let's make a mode selector.
|
||||
|
||||
if "analytics_middle_graph_mode" not in win.current:
|
||||
win.current["analytics_middle_graph_mode"] = "pulse"
|
||||
win.current["analytics_middle_graph_mode"] = "linear"
|
||||
|
||||
for num, thing in enumerate(["linear", "analytics", "pulse"]): # By icons
|
||||
|
||||
|
@ -415,12 +478,12 @@ def layer(win):
|
|||
if "analytics_middle_graph_switch" not in win.current:
|
||||
win.current["analytics_middle_graph_switch"] = {
|
||||
"project":[True,"analytics", "progress_active"],
|
||||
"checklist":[True,"checklist", "darker_parts"],
|
||||
"rnd":[True,"scene", "node_videofile"],
|
||||
"chr":[True,"chr", "node_asset"],
|
||||
"veh":[True,"veh", "node_imagefile"], # Name in data : [ Active, Icon name, color ]
|
||||
"loc":[True,"loc", "node_blendfile"],
|
||||
"obj":[True,"obj", "node_badfile"]
|
||||
"checklist":[True,"checklist", "node_videofile"],
|
||||
"rnd":[True,"shot", "shot_5"],
|
||||
"chr":[True,"chr", "shot_1"],
|
||||
"veh":[True,"veh", "shot_2"], # Name in data : [ Active, Icon name, color ]
|
||||
"loc":[True,"loc", "shot_3"],
|
||||
"obj":[True,"obj", "shot_4"]
|
||||
}
|
||||
|
||||
cat = win.current["analytics_middle_graph_switch"]
|
||||
|
@ -434,9 +497,11 @@ def layer(win):
|
|||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+160+(40*num),
|
||||
225,
|
||||
38,
|
||||
40,
|
||||
40,
|
||||
10)
|
||||
10,
|
||||
fill=False)
|
||||
layer.stroke()
|
||||
|
||||
def do():
|
||||
cat[thing][0] = not cat[thing][0]
|
||||
|
@ -445,7 +510,7 @@ def layer(win):
|
|||
UI_elements.roundrect(layer, win,
|
||||
win.current["w"]/4+160+(40*num),
|
||||
225,
|
||||
40,
|
||||
38,
|
||||
40,
|
||||
10,
|
||||
do,
|
||||
|
@ -466,6 +531,8 @@ def layer(win):
|
|||
|
||||
# Now let's make a layer.
|
||||
|
||||
# CURRENT DATE
|
||||
today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
|
||||
|
||||
|
||||
if "graph_cashe" not in win.current:
|
||||
|
@ -483,7 +550,7 @@ def layer(win):
|
|||
#node.fill()
|
||||
|
||||
# helping line
|
||||
UI_color.set(node, win, "progress_background")
|
||||
UI_color.set(node, win, "progress_time")
|
||||
|
||||
if mode == "analytics":
|
||||
|
||||
|
@ -503,6 +570,7 @@ def layer(win):
|
|||
|
||||
node.stroke()
|
||||
|
||||
todayX = 0
|
||||
|
||||
for num, thing in enumerate(reversed(cat)):
|
||||
|
||||
|
@ -530,6 +598,9 @@ def layer(win):
|
|||
|
||||
graphX = width / duration * dn
|
||||
|
||||
if date == today:
|
||||
todayX = graphX
|
||||
|
||||
# Let's calculate the Y position of a given part on a graph
|
||||
|
||||
if "fractions" in dates[date]:
|
||||
|
@ -555,7 +626,57 @@ def layer(win):
|
|||
|
||||
node.stroke()
|
||||
|
||||
# Today
|
||||
UI_color.set(node, win, "button_clicked")
|
||||
node.move_to(todayX, 0)
|
||||
node.line_to(todayX, height)
|
||||
node.stroke()
|
||||
|
||||
win.current["graph_cashe"] = graphsurface
|
||||
|
||||
|
||||
# Dynamic elements of the graph!
|
||||
# I sense a possible bug here, since I will draw these on top
|
||||
# of a prebaked image. And something sometimes might not align
|
||||
# properly. I don't know how to deal with it quite yet, perhaps
|
||||
# you can try fixing the issue. LOL.
|
||||
|
||||
# Bottom Graph position on the top graph.
|
||||
|
||||
try:
|
||||
posX = width / (duration*50) * win.scroll["days"]
|
||||
posX2 = (width / (duration*50) * (win.scroll["days"]+width))-posX
|
||||
except:
|
||||
posX = 0
|
||||
posX2 = 20
|
||||
UI_color.set(layer, win, "dark_overdrop")
|
||||
UI_elements.roundrect(layer, win,
|
||||
x-posX,
|
||||
y,
|
||||
posX2,
|
||||
height,
|
||||
5,
|
||||
fill=True)
|
||||
layer.stroke()
|
||||
|
||||
# Mouse drag thingy
|
||||
if x < win.current["mx"] < x+width\
|
||||
and y < win.current["my"] < y+height:
|
||||
if win.current["LMB"]:
|
||||
win.scroll["days"] = 0- (( win.current["mx"] - x ) / width * (duration*50)) + (width/2)
|
||||
|
||||
sd = datetime.datetime.strptime(startdate, new_date_format)
|
||||
daysin = int(round( duration / width * (x-win.current["mx"])))*-1
|
||||
td = datetime.timedelta(days=daysin)
|
||||
hoverdate = sd + td
|
||||
hoverdate = hoverdate.strftime(new_date_format)
|
||||
|
||||
UI_elements.tooltip(win, datetip(win, hoverdate))
|
||||
UI_color.set(layer, win, "progress_background")
|
||||
layer.move_to(win.current["mx"], y)
|
||||
layer.line_to(win.current["mx"], y+height)
|
||||
layer.stroke()
|
||||
|
||||
# Outputting the layer
|
||||
layer.set_source_surface(win.current["graph_cashe"], x, y)
|
||||
layer.paint()
|
||||
|
@ -617,8 +738,6 @@ def layer(win):
|
|||
do,
|
||||
button)
|
||||
|
||||
# CURRENT DATE
|
||||
today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
|
||||
|
||||
UI_elements.text(layer, win, "current_date_setting",
|
||||
x+100,
|
||||
|
@ -678,7 +797,8 @@ def layer(win):
|
|||
|
||||
prevyear = [startdate.split("/")[0], win.scroll["days"]]
|
||||
prevmonth = [startdate.split("/")[1], win.scroll["days"]]
|
||||
|
||||
prevday = "1997/07/30"
|
||||
pfrac = {}
|
||||
|
||||
for doffset in range(duration+1): # FOR ALL DAYS. NO MATTER IF THEY ARE IN DATA
|
||||
|
||||
|
@ -858,7 +978,8 @@ def layer(win):
|
|||
10,
|
||||
button=do,
|
||||
offset=[x,y],
|
||||
fill=False)
|
||||
fill=False,
|
||||
tip=datetip(win, theday))
|
||||
node.stroke()
|
||||
|
||||
##################### BOTTOM GRAPH #######################
|
||||
|
@ -873,28 +994,72 @@ def layer(win):
|
|||
# need to be able to navigate with in the bottom graph.
|
||||
|
||||
# So instead I'm going to redo the graph, but since we
|
||||
# are re-doing it. I gonna make a slightly different design.
|
||||
# It will show the same exact data. But drawn with a bit more
|
||||
# beauty, compared to the top graph.
|
||||
# are re-doing it. I orignally wanted to do a different
|
||||
# design. But it ended up looking confusing. It needs lines!
|
||||
# Roundrects will not do.
|
||||
|
||||
|
||||
|
||||
for num, thing in enumerate(reversed(cat)):
|
||||
if cat[thing][0]:
|
||||
UI_color.set(node, win, cat[thing][2])
|
||||
try:
|
||||
|
||||
sd = datetime.datetime.strptime(startdate, new_date_format)
|
||||
nd = datetime.datetime.strptime(theday , new_date_format)
|
||||
|
||||
dn = nd - sd
|
||||
dn = int(dn.days)
|
||||
|
||||
fracs = win.analytics["dates"][theday]["fractions"]
|
||||
Pfracs = win.analytics["dates"][prevday]["fractions"]
|
||||
|
||||
gfraction = fracs[thing]
|
||||
# For now I will implement only Linear mode
|
||||
# other modes will come later
|
||||
|
||||
if mode == "linear":
|
||||
|
||||
graphY = ((height-80) - (height-80) * gfraction)+60
|
||||
|
||||
UI_elements.roundrect(node, win,
|
||||
8+current_X+win.scroll["days"],
|
||||
graphY,
|
||||
35,
|
||||
8,
|
||||
5)
|
||||
elif mode == "analytics":
|
||||
tfraction = dn / duration
|
||||
gfraction = gfraction / tfraction / 2
|
||||
graphY = ((height-80) - (height-80) * gfraction)+60
|
||||
|
||||
|
||||
else:
|
||||
try:
|
||||
gfraction = fracs[thing]
|
||||
gfraction = gfraction - Pfracs[thing]
|
||||
except:
|
||||
pass
|
||||
gfraction = 0
|
||||
graphY = ((height-80) - (height-80) * gfraction - (height-80) / 2)+60
|
||||
|
||||
PgraphY = pfrac.get(thing, graphY)
|
||||
pfrac[thing] = graphY
|
||||
|
||||
node.move_to(current_X+win.scroll["days"]-25,
|
||||
PgraphY)
|
||||
node.line_to(current_X+win.scroll["days"]+25,
|
||||
graphY)
|
||||
node.stroke()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
except Exception as e:
|
||||
if theday < today and theday not in win.analytics["dates"]:
|
||||
UI_color.set(node, win, "node_badfile")
|
||||
UI_elements.roundrect(node, win,
|
||||
5+current_X+win.scroll["days"],
|
||||
67,
|
||||
40,
|
||||
height-67,
|
||||
10,
|
||||
fill=False)
|
||||
node.stroke()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -903,6 +1068,28 @@ def layer(win):
|
|||
# Now here I want to draw the representations of scheduled
|
||||
# tasks that are inside
|
||||
|
||||
# Icons of what was done at the day
|
||||
icons_stuff = {"assets":"obj",
|
||||
"scenes":"shot",
|
||||
"files":"checklist"}
|
||||
icons = []
|
||||
for t in icons_stuff:
|
||||
if t in win.analytics["dates"].get(theday, {}) and t != "assets":
|
||||
icons.append(icons_stuff[t])
|
||||
elif t in win.analytics["dates"].get(theday, {}):
|
||||
for at in ["chr", "obj", "loc", "veh"]:
|
||||
for stuff in win.analytics["dates"].get(theday, {})[t]:
|
||||
if at in stuff and at not in icons:
|
||||
icons.append(at)
|
||||
|
||||
for nicon, icon in enumerate(icons):
|
||||
UI_elements.image(node, win, "settings/themes/"\
|
||||
+win.settings["Theme"]+"/icons/"+icon+".png",
|
||||
6+current_X+win.scroll["days"],
|
||||
height-(50*nicon)-50,
|
||||
40,
|
||||
40)
|
||||
|
||||
sch = []
|
||||
if theday in win.analytics["dates"]:
|
||||
date = win.analytics["dates"][theday]
|
||||
|
@ -938,8 +1125,12 @@ def layer(win):
|
|||
5)
|
||||
|
||||
|
||||
|
||||
|
||||
current_X = current_X + 50
|
||||
|
||||
prevday = theday
|
||||
|
||||
|
||||
UI_color.set(node, win, "dark_overdrop")
|
||||
UI_elements.roundrect(node, win,
|
||||
|
|
|
@ -268,6 +268,12 @@ def pmdrawing(pmdrawing, main_layer, win):
|
|||
# Current frame (for animations and things like this)
|
||||
win.current["frame"] += 1
|
||||
|
||||
|
||||
if win.current["frame"] == 10:
|
||||
win.cur = "/set"
|
||||
win.url = "analytics"
|
||||
|
||||
|
||||
if not "scale" in win.settings:
|
||||
settings.write("scale", 1) # Writing to file
|
||||
win.settings = settings.load_all()
|
||||
|
|
|
@ -151,7 +151,7 @@ def layer(win):
|
|||
slist.append([date, item, schedules[date][item]])
|
||||
|
||||
|
||||
# Now that we have our list we can start paring it the same way as in the
|
||||
# Now that we have our list we can start parsing it the same way as in the
|
||||
# scheduling. Only removing some unnesesary stuff.
|
||||
foundtask = False
|
||||
taskname = ""
|
||||
|
|
Loading…
Reference in a new issue