Lokaverkefni LIRU 2018: Háskólinn í Reykjavík

Framvindugögn og Framsetning

Eftir Axel Björnsson, Darra Valgarðsson og Eddu Steinunni Rúnarsdóttur

Það kerfi sem notað er í dag til að reikna greiðslumat umsækjanda í Landsbankanum er gluggaforrit sem keyrir í Windows tölvum, þ.e. Windows Forms client sem er ein eining af safni slíkra gluggaforrita sem saman mynda eitt heildar innrakerfi sem starfsmenn Landsbankans nota daglega í ýmsum tilgangi. Greiðslumatskerfið talar við áreiðanlega vefþjónustu sem talar bæði við gagnagrunn bankans og gagnagrunn á vegum Creditinfo.

Þó greiðslumatskerfið geti gert það sem til er ætlast af því er erfitt að vinna í því. Flæði kerfisins er erfitt, gallar eru til staðar, það er erfitt að eiga endurkvæmt úr ýmsum aðgerðum sem eru framkvæmdar í kerfinu, útlitið er hrátt, ýmist of lítið eða of mikið af upplýsingum er birt hverju sinni og ýmsar skjámyndir kerfisins hafa yfirgnæfandi mikið efni sem gerir það óaðgengilegt. Allt þetta dregur úr virkni og þægindum kerfisins sem getur verið erfitt í daglegri notkun.

Mörg innrakerfi þessa heildar innrakerfis eru einnig erfið að vinna í og því er verið að skoða þann möguleika að koma innrakerfinu í heild sinni á netið þar sem sjálfvirk auðkenning er notuð líkt og í fyrra kerfi, að einingarnar geri það sem til er ætlast af þeim eins og áður, en bætt útlit og bætt flæði í er fyrirrúmi.

Sem fyrsta skref í þessarri aðgerð stendur til að setja eitt þessarra gluggaforrita á vefinn, það er greiðslumatskerfið. Það skal hafa bætt útliti, flæði og virkni. Teymið hefur tekið þetta verkefni að sér og er það lokaverkefni í Háskólanum í Reykjavík. Sjái teymið fram á að geta tekið að sér stærra umfang á meðan á lokaverkefninu stendur er möguleiki á að útvíkkun verði á verkefninu. Þá mun teymið hefja samþættingu á heildar innrakerfinu yfir á vefinn. Hvort sem tími gefst í það eða ekki þarf teymið að hafa huga í sinni vinnu að greiðslumatskerfið mun mögulega vera samþætt inn í heildar innrakerfið síðar meir ef það verður skrifað yfir á vefinn líka.

Eftirfarandi skjal inniheldur öll gögn um framvindu verkefnisins sem var byggð upp á meðan verkefninu stóð. Gögnin eru sett fram í formi framvindurits (Burndown chart) og verkefnakökuriti (productivity pie) til samantektar á vinnu gerða í spretti í formi stikkorða.

Nauðsynleg forritunarsöfn sett inn

In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random
import plotly as py
import plotly.graph_objs as go
import matplotlib as mpl
import matplotlib.dates as mdates
import datetime
import matplotlib.dates as mdates
import matplotlib.cbook as cbook
import seaborn as sns 
import matplotlib.patches as mpatches
import plotly.plotly as py
import plotly.graph_objs as go

mpl.style.use('seaborn-darkgrid')

Frumstilling gagna

Tvö gagnasett eru byggð upp. Eitt er framvindugagnasettið sem geymir öll gögn um framvindu, þ.e. unna tíma, forgangssögupunkta sem eftir eru og heildarsögupunkta sem eftir eru og dagsetningar þeirra. og kaffibollagagnasettið sem geymir yfrlit yfir kaffidrykkju á meðan verkefni stendur. Bæði gagnasett eru byggð upp innan þessa skjals til að allar upplýsingar komi sem skýrast fram í skjalinu.

In [2]:
initialStoryPoints = 323
initialPriorityStoryPoints = 298
StoryPointsRemaining = 323
PriorityStoryPointsRemaining = 298
ActualData = {'Entry' : [0], 'Day': ['22/01/2018'], 'Sprint' : [0], 'SPR' : [initialStoryPoints], 'PSPR' : [initialPriorityStoryPoints], 'DayWork' : ['Undirbúningur: Framvinduskýrsla'], 'Hours' : [2]}
ActualData = pd.DataFrame(data=ActualData)
In [3]:
CoffeTracker = {'Entry': [0], 'Sprint' : [0], 'Weekday' : 'Thursday', 'Edda' : [0], 'Darri' : [0], 'Axel' : [0]}
CoffeTracker = pd.DataFrame(data=CoffeTracker)

Yfirlýsing og útfærsla fallna til framsetningar og gagnavinnslu

Eftirfarandi eru föll til aðstoðar við framsetningu eða innsetningu gagna

Gagnasetshjálparföll

Fallð updateDF uppfærir raungögn fyrir framvindugagnasettið

In [4]:
def updateDF(DF, day, sprint, workdone, hours, completedSP=0, completedPSP=0):
    global StoryPointsRemaining, PriorityStoryPointsRemaining
    StoryPointsRemaining -= completedSP
    PriorityStoryPointsRemaining -= completedPSP
    return DF.append({'Entry' : len(ActualData.index), 'Day': day, 'Sprint' : sprint, 'SPR' : StoryPointsRemaining, 'PSPR' : PriorityStoryPointsRemaining, 'DayWork' : workdone, 'Hours' : hours}, ignore_index=True)

Fallið updateCoffe uppfærir raungögn fyrir kaffibollagagnasettið

In [5]:
def updateCoffee(DF, sprint, weekday, edda, darri, axel):
    return DF.append({'Entry' : len(CoffeTracker.index), 'Sprint' : sprint, 'Weekday' : weekday, 'Edda' : edda, 'Darri' : darri, 'Axel' : axel}, ignore_index=True)

Gagnaframsetningarhjálparföll

Fallið makeMePieChartFromSprint býr til verkefnakökurit fyrir sprett sem sendur er inn sem færibreyta sem tölustafur og táknar sprettsnúmer (0 er upphafssprettur)

In [6]:
# Generates productivity pie chart for a given sprint

def makeMePieChartFromSprint (sprint):
    
    # Frequency table created
    DayWorkDF = ActualData
    DayWorkDF = DayWorkDF[DayWorkDF['Sprint'] == sprint]
    DayWorkDF = DayWorkDF.loc[:, ['DayWork', 'Hours']]
    DayWorkDF = DayWorkDF.groupby(['DayWork'])['Hours'].sum().reset_index()
    DayWorkDF.sort_values(by=['Hours'], ascending=False)
    
    # Pallette
    cpallette = sns.color_palette("husl", 8)

    font = {'size'   : 16}
    plt.rc('font', **font)
    
    plt.pie( DayWorkDF.Hours,
             colors=cpallette,
             autopct='%1.1f%%',
             shadow=False,
             startangle=90 )
    
    plt.legend(DayWorkDF.DayWork, bbox_to_anchor=(1,0), loc="lower right", bbox_transform=plt.gcf().transFigure)
    
    plt.title('Verkefnayfirlit fyrir sprett ' + str(sprint), fontsize=20)
    plt.tight_layout()
    fig = plt.gcf()
    fig.set_size_inches(13,7)
    plt.axis('equal')
    plt.savefig('VerkefnayfirlitSprettur' + str(sprint) + '.jpg')

Fallið makeMePieChartForAllSprints gerir verkefnayfirlit úr yfirflokkum þeirra verkefna sem unnin eru fyrir alla spretti

In [7]:
def truncate_colon(dw):
    return dw.split(':')[0]

def makeMePieChartForAllSprints ():
    
    # Frequency table created
    DayWorkDF = ActualData
    DayWorkDF = DayWorkDF.loc[:, ['DayWork', 'Hours']]
    DayWorkDF['DayWork'] = DayWorkDF['DayWork'].apply(truncate_colon)
    DayWorkDF = DayWorkDF.groupby(['DayWork'])['Hours'].sum().reset_index()
    DayWorkDF.sort_values(by=['Hours'], ascending=False)
    
    # Pallette
    cpallette = sns.color_palette("husl", 8)

    font = {'size'   : 16}
    plt.rc('font', **font)
    
    plt.pie( DayWorkDF.Hours,
             colors=cpallette,
             autopct='%1.1f%%',
             shadow=False,
             startangle=90 )
    
    plt.legend(DayWorkDF.DayWork, bbox_to_anchor=(1,0), loc="lower right", bbox_transform=plt.gcf().transFigure)
    
    plt.title('Verkefnayfirlit fyrir spretti ', fontsize=20)
    plt.tight_layout()
    fig = plt.gcf()
    fig.set_size_inches(13,7)
    plt.axis('equal')
    plt.savefig('Verkefnayfirlit' + '.jpg')

Fallið plotBurndownChartFromSprint býr til burndown framvindu fyrir sprett sem sendur er inn sem færibreyta sem tölustafur og táknar sprettsnúmer (0 er upphafssprettur). Hann býr einnig til flata línu til að setja fram myndræna framsetningu á sprettsmarkmiði sem er einnig send inn sem færibreyta í fallið.

In [8]:
# PLOTS BURNDOWNCHART FROM SPRINT

def plotBurndownChartFromSprint (sprint, goal) :
    
    ## SETUP FOR NEW BD CHART
    df1 = ActualData
    df1 = df1.drop(['DayWork'], axis=1)
    df1=df1.sort_values(by='Entry', ascending=True)
    df1 = df1.drop(['Entry'], axis=1)
    df2 = df1
    df3 = df1
    df2= df2.groupby(['Day'], sort=False)['Hours'].sum().reset_index()
    df1= df1.groupby(['Day'], sort=False)['PSPR', 'SPR'].min().reset_index()
    df3= df3.groupby(['Day'], sort=False)['Sprint'].min().reset_index()

    resultdf = pd.concat([df1, df2, df3], axis=1)
    resultdf = resultdf.loc[:,~resultdf.columns.duplicated()]
    resultdf = resultdf[resultdf['Sprint'] == sprint].reset_index()

    ax = []

    # Pallette
    cpallette = 'purple'
    AColor = '#99ffeb'
    AAColor = '#00cca3'
    EColor = '#ffcc99'
    EEColor = '#ff9933'

    #create upper subplot
    plt.figure(figsize = (20, 20))
    font = {'size'   : 16}
    plt.rc('font', **font)
    ax.append(plt.subplot(211))
    plt.xticks(range(len(resultdf.Day)), resultdf.Day)
    plt.plot(resultdf.index, resultdf.SPR, '--',
             marker='o',
             color=EColor,
             linewidth=1.9,
             label=resultdf.SPR)
    plt.plot(resultdf.index, resultdf.PSPR,
             marker='o',
             color=AAColor,
             linewidth=1.9,
             label=resultdf.PSPR)
    if(goal != -1):
        plt.axhline(y=goal, color='#FE5F55', linestyle='--')
    plt.ylim(resultdf.PSPR.min()-100,resultdf.SPR.max()+35)
    plt.yticks([])
    plt.fill_between(resultdf.index, resultdf.PSPR, color=AColor, alpha='0.6')
    plt.fill_between(resultdf.index, resultdf.SPR, color=EColor, alpha='0.1')
    for i in range(len(resultdf)):
        plt.text(i, resultdf.SPR[i] + 3, resultdf.SPR[i], ha='center', va='bottom')
        plt.text(i, resultdf.PSPR[i] + 3, resultdf.PSPR[i], ha='center', va='bottom')

    #create plot on secondary y-axis of upper subplot
    ax.append(ax[0].twinx())
    plt.bar( resultdf.index,
             list(resultdf.Hours),
             width=0.2,
             color=cpallette,
             alpha=0.6)
    plt.yticks([])
    for i in range(len(resultdf)):
        plt.text(i, resultdf.Hours[i], resultdf.Hours[i], ha='center', va='bottom')
    plt.ylim(0, 100)
    font = {'size'   : 12}
    plt.rc('font', **font)
    all_patch = mpatches.Patch(color=EEColor, label='Heildarsögupunktar eftir')
    priority_patch = mpatches.Patch(color=AAColor, label='Heildarforgangssögupunktar eftir')
    hours_patch = mpatches.Patch(color='purple', label='Klukkustundir unnar')
    if(goal != -1):
        goal_patch = mpatches.Patch(color='#FE5F55', label='Markmið spretts (forgangssögupunktar)')
        plt.legend(handles=[all_patch, priority_patch, hours_patch, goal_patch], fontsize='large')
    else:
        plt.legend(handles=[all_patch, priority_patch, hours_patch], fontsize='large')
    plt.title('Burndown Framvindurit fyrir sprett ' + str(sprint), fontsize=20)
    plt.xlabel('Dags', fontsize=12)
    plt.savefig('BurndownSprettur' + str(sprint) + '.jpg')
    plt.show()

Fallið plotBurndownChartForAllSprints teiknar upp framvindurit líkt og fallið að ofan en fyrir allt verkefnið í heild sína, þ.e. alla spretti verkefnisins í einu

In [9]:
# PLOTS BURNDOWNCHART FROM SPRINT

def plotBurndownChartForAllSprints () :
    
    ## SETUP FOR NEW BD CHART
    df1 = ActualData
    df1 = df1.drop(['DayWork'], axis=1)
    df1=df1.sort_values(by='Entry', ascending=True)
    df1 = df1.drop(['Entry'], axis=1)
    df2 = df1
    df3 = df1
    df2= df2.groupby(['Day'], sort=False)['Hours'].sum().reset_index()
    df1= df1.groupby(['Day'], sort=False)['PSPR', 'SPR'].min().reset_index()
    df3= df3.groupby(['Day'], sort=False)['Sprint'].min().reset_index()

    resultdf = pd.concat([df1, df2, df3], axis=1)
    resultdf = resultdf.loc[:,~resultdf.columns.duplicated()]

    ax = []

    # Pallette
    cpallette = 'purple'
    AColor = '#99ffeb'
    AAColor = '#00cca3'
    EColor = '#ffcc99'
    EEColor = '#ff9933'

    #create upper subplot
    plt.figure(figsize = (20, 20))
    font = {'size'   : 16}
    plt.rc('font', **font)
    ax.append(plt.subplot(211))
    plt.xticks(range(len(resultdf.Day)), resultdf.Day)
    plt.plot(resultdf.index, resultdf.SPR, '--',
             marker='o',
             color=EColor,
             linewidth=1.9,
             label=resultdf.SPR)
    plt.plot(resultdf.index, resultdf.PSPR,
             marker='o',
             color=AAColor,
             linewidth=1.9,
             label=resultdf.PSPR)
    plt.ylim(resultdf.PSPR.min()-260,resultdf.SPR.max()+55)
    plt.xticks(rotation=90)
    plt.yticks([])
    plt.fill_between(resultdf.index, resultdf.PSPR, color=AColor, alpha='0.6')
    plt.fill_between(resultdf.index, resultdf.SPR, color=EColor, alpha='0.1')
    for i in range(len(resultdf)):
        plt.text(i, resultdf.SPR[i] + 3, resultdf.SPR[i], ha='center', va='bottom')
        plt.text(i, resultdf.PSPR[i] + 3, resultdf.PSPR[i], ha='center', va='bottom')

    #create plot on secondary y-axis of upper subplot
    ax.append(ax[0].twinx())
    plt.bar( resultdf.index,
             list(resultdf.Hours),
             width=0.2,
             color=cpallette,
             alpha=0.6)
    plt.xticks(rotation=90)
    plt.yticks([])
    for i in range(len(resultdf)):
        plt.text(i, resultdf.Hours[i], resultdf.Hours[i], ha='center', va='bottom')
    plt.ylim(0, 100)
    all_patch = mpatches.Patch(color=EEColor, label='Heildarsögupunktar eftir')
    priority_patch = mpatches.Patch(color=AAColor, label='Heildarforgangssögupunktar eftir')
    hours_patch = mpatches.Patch(color='purple', label='Klukkustundir unnar')
    plt.legend(handles=[all_patch, priority_patch, hours_patch], fontsize='large')
    font = {'size'   : 12}
    plt.rc('font', **font)
    plt.title('Burndown Framvindurit fyrir LIRU Lokaverkefni', fontsize=23)
    plt.xlabel('Dags', fontsize=12)
    plt.savefig('Burndown Framvindurit fyrir LIRU Lokaverkefni' + '.jpg')
    plt.show()

Fallið thursdaysVsFridaysCoffeePieChart setur fram mun á kaffineyslu á fimmtudögum og föstudögum meðal teymis

In [10]:
# Generates coffee pie of thursdays vs fridays

def thursdaysVsFridaysCoffeePieChart ():
    
    # Frequency table created
    CoffePie = CoffeTracker
    CoffePie = CoffePie.loc[:, ['Axel', 'Darri', 'Edda', 'Weekday']]
    CoffePie = CoffePie.groupby(['Weekday'])['Axel', 'Darri', 'Edda'].sum().reset_index()
    CoffePie.sort_values(by=['Weekday'], ascending=False)
    CoffePie['totalCoffee'] = CoffePie.apply(lambda row: row.Edda + row.Darri + row.Axel, axis=1)
    CoffePie = CoffePie.loc[:, ['Weekday', 'totalCoffee']]
    
    # Pallette
    cpallette = sns.color_palette("husl", 8)

    font = {'size'   : 16}
    plt.rc('font', **font)
    
    plt.bar( CoffePie.Weekday,
             list(CoffePie.totalCoffee),
             color=cpallette)
    
    plt.title('Fimmtudagar vs Föstudagar: Kaffi', fontsize=20)
    plt.tight_layout()
    fig = plt.gcf()
    fig.set_size_inches(7,6)
    #plt.axis('equal')
    plt.savefig('LokaverkefniKaffiFimmtudagarVsFöstudagar.jpg')

Fallið whoWinsCoffeePlot setur fram muninn á kaffineyslu fyrir hvern teymismeðlim fyrir sig

In [11]:
# Generates coffee pie of thursdays vs fridays

def whoWinsCoffeePlot ():
    
    # Frequency table created
    CoffeIndividual = CoffeTracker.groupby(['Weekday'])['Axel', 'Darri', 'Edda'].sum()
    CoffeIndividual = CoffeIndividual.loc[:, ['Axel', 'Darri', 'Edda']].sum().reset_index()
    CoffeIndividual = CoffeIndividual.groupby(['Axel', 'Darri', 'Edda']).sum()
    
    # Pallette
    cpallette = sns.color_palette("husl", 8)

    font = {'size'   : 16}
    plt.rc('font', **font)
        
    plt.bar( CoffeIndividual.index,
             list(CoffeIndividual.loc[:, 0]),
             color=cpallette,)
    
    plt.title('Hver vinnur kaffi?', fontsize=20)
    plt.tight_layout()
    fig = plt.gcf()
    fig.set_size_inches(5,6)
    #plt.axis('equal')
    plt.savefig('LokaverkefniKaffiWinner.jpg')

Sprettur 0: Upphafssprettur

Upphafsspretturinn stóð yfir í tvær vikur samkvæmt áætlun, dagana 8. janúar - 22. janúar. Lokaverkefni var fengið hjá Landsbankanum og fundað var tvisvar með tengiliðum bankans um fyrirkomulag og verkefni. Sett var upp beinagrind fyrir verklag; í aðalatriðum var gert ráð fyrir u.þ.b. 16 vinnutímum fyrir hvern hópmeðlim í viku í verkefnið eða tveir heilir vinnudagar í viku, fimmtudag og föstudag. 38 tímar fóru alls í upphafssprettinn sem er um 40% af vinnutíma samkvæmt hinni nýju áætlun. Hins vegar tekur sú prósenta af vinnutíma mið af því að ekki var búið að útvega okkur aðgengi að kerfinu og þar af leiðandi gátum við ekki byrjað að gera kröfulista og frumgerðahönnun. Í staðinn undirbjuggum við skýrslugerð og verklag eftir bestu getu, svo langt sem það náði.

Gögn sett inn í gagnasett

In [12]:
## FOR SPRINT 0 ACTUAL DATA
sprint = 0
ActualData = updateDF (ActualData, '08/01/2018', sprint, 'Fundur við fyrirtæki', 3*1)
ActualData = updateDF (ActualData, '15/01/2018', sprint, 'Fundur við fyrirtæki', 3*4)
ActualData = updateDF (ActualData, '17/01/2018', sprint, 'Skýrslugerð', 3)
ActualData = updateDF (ActualData, '17/01/2018', sprint, 'Undirbúningur: Frumgerðahönnun', 3)
ActualData = updateDF (ActualData, '19/01/2018', sprint, 'Undirbúningur: Verklagsundirbúningur', 3*5)
ActualData = updateDF (ActualData, '19/01/2018', sprint, 'Skýrslugerð', 2)
# Tjékka hvort passar
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 0: 40

Framsetning gagna

In [13]:
# Plot and save figure from a sprint
makeMePieChartFromSprint(0)
plt.show()

Sprettur 1

Fyrsti spretturinn stóð yfir í tvær vikur samkvæmt áætlun dagana 22. janúar - 5. febrúar. Í spretti 1 var fyrst og fremst fundað með tengiliðum bankans til að komast vel inn í kerfið, til þess að sammælast um þau tæki og tól sem okkur ber að nota og til þess að sammælast um kröfulista. Sett var upp beinagrind að hönnun sem sjá má í kafla 4.1 sem sýnir grófa mynd af frumgerðum sem voru búnar til sem upphafleg hugsun á hönnun, með fyrirvara um að breyting verði á þeirri hönnun. Upphaflegur kröfulisti var settur saman eins og sjá má í kafla 7.1 en þar eru komnar tæpar 40 kröfur. Enn á eftir að framkvæma sögupunktamat, en það verður gert síðar, eða við upphaf forritunar til þess að mat þeirra verði sem nákvæmast. Alls fóru 94 tímar í sprett 1 sem er um 100% af vinnutíma samkvæmt áætlun.

Gögn sett inn

In [14]:
## SPRETTUR 1
# 22 jan
ActualData = updateDF (ActualData, '22/01/2018', 1, 'Skýrslugerð', 5*3)
# 26 jan
ActualData = updateDF (ActualData, '26/01/2018', 1, 'Skýrslugerð', 2*3)
ActualData = updateDF (ActualData, '26/01/2018', 1, 'Fundur við fyrirtæki', 4*3)
ActualData = updateDF (ActualData, '26/01/2018', 1, 'Undirbúningur: uppsetning þróunartóla', 2*2+1, 2*2+1, 2*2+1) # SETJA UPP ÞRÓUNARUMHV
#29 jan
ActualData = updateDF (ActualData, '29/01/2018', 1, 'Undirbúningur: Kynningarundirbúningur', 2*3)
#1 feb
ActualData = updateDF (ActualData, '01/02/2018', 1, 'Fundur við fyrirtæki', 8, 8, 8) ## LÆRA Á FYRRA KERFI
ActualData = updateDF (ActualData, '01/02/2018', 1, 'Undirbúningur: Þarfagreining', 2*3)
ActualData = updateDF (ActualData, '01/02/2018', 1, 'Undirbúningur: Frumgerðahönnun', 2*3)
#2 feb
ActualData = updateDF (ActualData, '02/02/2018', 1, 'Fundur við fyrirtæki', 2*3)
ActualData = updateDF (ActualData, '02/02/2018', 1, 'Undirbúningur: Þarfagreining', 3*3)
ActualData = updateDF (ActualData, '02/02/2018', 1, 'Undirbúningur: Frumgerðahönnun', 5*3)
# Tjékka hvort passar
sprint = 1
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 1: 94

Framsetning gagna

In [15]:
makeMePieChartFromSprint(1)
plotBurndownChartFromSprint(1, -1)
plt.show()

Sprettur 2

Annar spretturinn stóð yfir í tvær vikur samkvæmt áætlun dagana 5. febrúar - 19. febrúar. Í spretti 2 var fyrst og fremst reynt að hefja forritun með tilheyrandi rannsóknum og upplýsingaöflun á vefþjónustu, forritunarumhverfi og forritunarverkþættir voru brotnir niður. Einu sinni var fundað með tengiliðum bankans til að athuga hvort teymið væri ekki örugglega að gera allt samkvæmt þeirra kröfum. Sett var upp beinagrind að forritunarverkefninu með tilheyrandi þörfum (e. dependencies) og forritunarumhverfi er nú mest uppsett. Byrjað var að forrita eina skjámynd, einstaklingsleit, en gróf hönnun á henni má sjá í kafla 4.1.1. Enn á eftir að framkvæma sögupunktamat, en það verður gert síðar, eða þegar teymið er komið aðeins áleiðis með forritunina þannig að mat þeirra verði sem nákvæmast. Alls fóru 75 tímar í sprett 2 sem er u.þ.b. 80% af vinnutíma samkvæmt áætlun. Teymið tók meðvitaða ákvörðun að vinna aðeins þrjá daga í stað fjóra í sprett 2 (engu að síður langa þrjá vinnudaga) vegna þess að takmörkuð kunnátta á ReactJS kynni að aftra framvindu, svo teymið ákvað að betra væri að kynnast React vel á eigin tíma í þessum spretti til að vera sem afkastamest í þeim næsta. Teymið mun koma til með að vinna einn aukadag í komandi sprettum í stað þess sem glataðist, í hvaða spretti fer eftir tilmælum bankans og hvenær aðstæða sé laus.

Gögn sett inn

In [16]:
## SPRETTUR 2
# FEB 9
ActualData = updateDF (ActualData, '09/02/2018', 2, 'Skýrslugerð', 3)
ActualData = updateDF (ActualData, '09/02/2018', 2, 'Skýrslugerð', 3*3, 3, 3)
ActualData = updateDF (ActualData, '09/02/2018', 2, 'Undirbúningur: Rannsókn (API/ReactJS)', 3*5, 3, 3)
# FEB 15
ActualData = updateDF (ActualData, '15/02/2018', 2, 'Fundur við fyrirtæki', 3*1, 3, 3)
ActualData = updateDF (ActualData, '15/02/2018', 2, 'Undirbúningur: Uppsetning verkefnis', 3*3, 3, 3)
ActualData = updateDF (ActualData, '15/02/2018', 2, 'Forritun: Tengjast Vefþjónustu', 3*4, 5, 5)
# FEB 16
ActualData = updateDF (ActualData, '16/02/2018', 2, 'Forritun: Einstaklingaleit', 3*6, 10, 10)
ActualData = updateDF (ActualData, '16/02/2018', 2, 'Undirbúningur: Kynningarundirbúningur', 3*2, 5, 5)
# Tjékka hvort passar
sprint = 2
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 2: 75

Framsetning gagna

In [17]:
# Burndown and productivity pie from sprint 2
makeMePieChartFromSprint(2)
plotBurndownChartFromSprint(2, 253)
plt.show()

Sprettur 3

Þriðji spretturinn stóð yfir í tvær vikur samkvæmt áætlun dagana 5. febrúar - 19. febrúar. Í spretti 3 var fyrst og fremst klárað að setja upp sjálvirkt auðkenni/leyfi til að eiga samskipti við gagnagrunninn (API). Það hófst og sett var upp einstaklingaleit og sýnd greiðslumöt fyrir einstaklinga. Auk þess var kóði lagfærður og minniháttar villur lagaðar. Alls foru 75 klukkustundir í sprett 3 sem eru rúm 80% af vinnutíma. Veikindi voru meðal teymisins sem skýrir fjarveruna.

Gögn sett inn

In [18]:
## SPRETTUR 3
# FEB 22
ActualData = updateDF (ActualData, '22/02/2018', 3, 'Skýrslugerð: Sögupunktamat', 1)
ActualData = updateDF (ActualData, '22/02/2018', 3, 'Skýrslugerð: Sögupunktamat', 3*3-1)
ActualData = updateDF (ActualData, '22/02/2018', 3, 'Forritun: Einstaklingsleit', 3*2, 4, 4)
ActualData = updateDF (ActualData, '22/02/2018', 3, 'Undirbúningur: Continous Integration', 5, 4, 4)
ActualData = updateDF (ActualData, '22/02/2018', 3, 'Forritun: Sjálfvirkt token', 7, 8, 8)
# FEB 23
ActualData = updateDF (ActualData, '23/02/2018', 3, 'Forritun: Sjálfvirkt token', (2*9)+1, 10, 10)
ActualData = updateDF (ActualData, '23/02/2018', 3, 'Forritun: Einstaklingsleit', 9, 5, 5)
# MARCH 1
ActualData = updateDF (ActualData, '01/03/2018', 3, 'Forritun: Einstaklingaleit', 8, 5, 4)
ActualData = updateDF (ActualData, '01/03/2018', 3, 'Forritun: Code Refactor', 8)
# MARCH 2
ActualData = updateDF (ActualData, '02/03/2018', 3, 'Forritun: Bug Fix', 3, 3, 3)
ActualData = updateDF (ActualData, '02/03/2018', 3, 'Forritun: Code Refactor', 2, 2)
ActualData = updateDF (ActualData, '02/03/2018', 3, 'Forritun: Einstaklingsleit', 3, 3, 3)
# Tjékka hvort passar
sprint = 3
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 3: 79

Framsetning gagna

In [19]:
# Burndown and productivity pie from sprint 3
makeMePieChartFromSprint(3)
plotBurndownChartFromSprint(3, 226)
plt.show()

Sprettur 4

Fjórði spretturinn stóð yfir í tvær vikur samkvæmt áætlun dagana 5. mars - 19. mars. Í spretti 4 var fyrst og fremst einblínt að birta þann aragrúa af upplýsingum sem fylgir niðurstöðum greiðslumats, þar á meðal laun, framfærslugjöld, rekstarkostnaður, börn, skuldir, o.s.frv. Mikil samskipti voru á milli teymis og hagsmunaaðilla vegna bætinga á birtingum á þessum upplýsingum, þ.e. til að birta ekki ónothæfar upplýsingar og birta þær sem skiptu máli. Náð var að birta allar upplýsingar og uppsetning var komin langt á veg í þessum spretti. Alls fóru 88 tímar í sprett 2 sem er u.þ.b. 92% af vinnutíma samkvæmt áætlun, en það er vegna veikinda teymismeðlims einn daginn. Markmiði spretts var náð; markmiðið fyrir sprett 4 var að brenna 51 forgangssögupunkti, en þar sem vel gekk með verkefni sprettsins tókst teyminu að útfæra aðra kröfu umfram þær sem stóð til útfæra í sprettinum og því voru 61 sögupunktar útfærðir.

Gögn sett inn

In [20]:
## SPRETTUR 4
sprint = 4
# MAR 8
ActualData = updateDF (ActualData, '08/03/2018', sprint, 'Skýrslugerð', 3*3)
ActualData = updateDF (ActualData, '08/03/2018', sprint, 'Útlit: MaterialUI', 2*3, 2, 2)
ActualData = updateDF (ActualData, '08/03/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 3*3, 7, 7)
# MAR 9
ActualData = updateDF (ActualData, '09/03/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 2*2, 2, 2)
ActualData = updateDF (ActualData, '09/03/2018', sprint, 'Forritun: Code Refactor', 2*2, 2, 2)
ActualData = updateDF (ActualData, '09/03/2018', sprint, 'Útlit: MaterialUI', 2*2, 2, 2)
ActualData = updateDF (ActualData, '09/03/2018', sprint, 'Forritun: Code Refactor', 2*2, 2, 2)
# MAR 15
ActualData = updateDF (ActualData, '15/03/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 3*8, 2*8+7, 2*8+6)
# MAR 16
ActualData = updateDF (ActualData, '16/03/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 3*8, 2*8+5, 2*8+5)
# Tjékka hvort passar
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 4: 88

Framsetning gagna

In [21]:
# Burndown and productivity pie from sprint 4
makeMePieChartFromSprint(4)
plotBurndownChartFromSprint(4, 161)
plt.show()

Sprettur 5

Fimmti spretturinn var óreglulegur og stóð ekki yfir í tvær vikur samkvæmt verklagsáætlunum vegna páskafrís og teymið vildi ekki missa vinnutíma vegna yfirvofandi prófatíðar. Sprettur fimm stóð yfir dagana 19. mars - 6. apríl, í þrjár vikur þar sem páskafrí var 29. mars, fimmtudegi. Í spretti 5 var fyrst og fremst einblínt að útfæra uppfærslu, eyðingu og bætingu á upplýsingum á því sem notandi má breyta af þeim aragrúa af upplýsingum sem fylgir niðurstöðum greiðslumats, þar á meðal launum, framfærslugjöldum, rekstarkostnað, börnum, skuldum, o.s.frv. Mikil samskipti voru á milli teymis og hagsmunaaðilla vegna bætinga á aðgerðum á þessum upplýsingum, þ.e. til að birta ekki láta notanda komast upp með að setja rangar upplýsingar og breyta því sem má ekki, en það eru einmitt praktísk atriði sem fyrra kerfi er afar villugjarnt á og getur hrunið við ýmsar aðgerðir notanda. Náð var að útfæra uppfærslu, eyðingu og bætingu fyrir mikið af þeim upplýsingum sem mátti uppfæra og öll tengd uppsetning var komin langt á veg í þessum spretti. Hins vegar, var umfangið á þessu töluvert meira en teymið hafði gert sér grein fyrir. Teymið hafði gert ráð fyrir mikilli vinnu við að útfæra þessar þrjár aðgerðir á hvern lið fyrir sig, en óraði ekki fyrir hversu erfiðar þessar aðgerðir yrðu á tekjur og skuldir. Ekki nóg með að fyrir þessa flokka hafði teymið sett upplýsingarnar upp vitlaust vegna misskilnings og þurfti að breyta uppsetningu alveg, en einnig var heilmikil gagnavinnsla og notendainntaksvinnsla sem teymið hafði ekki tekið með í reikninginn. Útfærsla á eyðingu, uppfærslu og bætingu fyrir þessa tvo flokka var því frestað fram í sprett 6. Alls fóru 87 tímar í sprett 2 sem er u.þ.b. 92% af vinnutíma samkvæmt áætlun, en það er aðallega vegna páskaringulreiðar og ferminga. Markmiði spretts var ekki náð eins og áður hafi verið tekið fram því ekki náðist að uppfæra, breyta og bæta laun og skuldir; markmiðið fyrir sprett 5 var að brenna 66 forgangssögupunktum og af þeim voru 42 sögupunktar brenndir. Eftir sprett 5 var komið að prófatíð og tók teymið sér hlé vegna undirbúnings prófa dagana 6. apríl til 21 apríl, en það hafði staðið til frá upphafi að taka hlé í prófunum.

Gögn sett inn

In [22]:
## SPRETTUR 5
## 42 ACHIEVED, 4 NON-PRI AND 46 GOAL
#DF, sprint, workdone, hours, completedSP=0, completedPSP=0
## 44 hrs total
sprint = 5

# MAR 22
ActualData = updateDF (ActualData, '22/03/2018', sprint, 'Útlit: MaterialUI', 5)
ActualData = updateDF (ActualData, '22/03/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 2*8+3, 10, 10)

# MAR 23
ActualData = updateDF (ActualData, '23/03/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 2*8, 6, 6)
ActualData = updateDF (ActualData, '23/03/2018', sprint, 'Útlit: MaterialUI', 4)

# MAR 28 (8*3 tímar)
ActualData = updateDF (ActualData, '28/03/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 3*8, 18, 18)

# APR 5 (2+2+5 timar)
ActualData = updateDF (ActualData, '5/04/2018', sprint, 'Fundur við fyrirtæki', 3*2)
ActualData = updateDF (ActualData, '5/04/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 3, 2, 2)

# APR 6 (10 timar)
ActualData = updateDF (ActualData, '5/04/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 10, 6, 6)

# Tjékka hvort passar
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 5: 87

Framsetning gagna

In [23]:
# Burndown and productivity pie from sprint 5
makeMePieChartFromSprint(5)
plotBurndownChartFromSprint(5, 86)
plt.show()

Sprettur 6

Sjötti spretturinn er fyrsti spretturinn í því þriggja vikna tímabili sem teymið er búið í prófum í öðrum áföngum og getur einblínt á verkefnið eingöngu. Eins og hafði staðið til með spretti eftir próf stóð þessi sprettur yfir í viku 21. apríl til 29. apríl, en fyrir sprett 6 var tekið hlé á verkefni vegna prófaundirbúnings (6. - 21. apríl) sem er fyrirkomulag sem hafði verið ákveðið í upphafi verkefnis og hafði verið gert ráð fyrir. Í spretti 6 var fyrst og fremst einblínt að klára alla virkni í kerfinu vegna þess að í sprett 7 stendur til að hætta að þróa virkni (að setja á svokallað feature freeze) til þess að vanprófuð og illa virkandi virkni sé ekki sett fram á síðustu stundu. Hins vegar þá var töluvert eftir enn af virkni í þessum spretti svo það stóð til að útfærsla eins virkniþátts af kröfulisa átti að geymast þar til í næsta spretti, það er að prenta út og afkóða tilheyrandi skjöl greiðslumats fyrir hvern viðskiptavin í greiðslumatinu. En þar sem teymið vildi vinna upp glataðan tíma gekk svo vel að þessi krafa var útfærð líka í spretti 6. Öllum eftirstandandi forgangssögupunktum var því brennt í spretti 6. Þó ber að hafa í huga að þó virkni kerfisins sé komin er margt eftir, þar á meðal að klára prófanir á kóða, gera notandaprófanir og það sem er mikilvægasti þáttur verkefnisins; útlit, villumeðhöndlun, endurgjöf og notandaupplifun, en það eru atriði sem teymið var beðið að bæta umfram gamla kerfisins. Sprettur 6 gekk vonum framar og teymið telur það vera vegna þess hve miklu munar að geta einblínt alveg að verkefninu án truflana frá öðrum áföngum og skyldum. Alls fóru 189 tímar í sprett 6 sem er u.þ.b. 200%, þ.e. tvöfaldur vinnutími samkvæmt áætlun vegna þess að teymið gat lokst unnið upp tapaðan tíma yfir önnina. Markmiði spretts var náð; markmiðið fyrir sprett 6 var að brenna 90 forgangssögupunkti, en þar sem vel gekk með verkefni sprettsins tókst teyminu að útfæra aðra kröfu umfram þær sem stóð til útfæra í sprettinum og því voru 110 sögupunktar útfærðir.

Gögn sett inn

In [24]:
## SPRETTUR 6
sprint = 6
# Apr 23 30 HRS
ActualData = updateDF (ActualData, '23/04/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 10*3, 27, 27)
# Apr 24 36 HRS
ActualData = updateDF (ActualData, '24/04/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 8*3, 15, 15)
ActualData = updateDF (ActualData, '24/04/2018', sprint, 'Útlit: Uppsetning', 4*3)
# Apr 25 30 HRS
ActualData = updateDF (ActualData, '25/04/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 5*3, 18, 18)
ActualData = updateDF (ActualData, '25/04/2018', sprint, 'Útlit: Uppsetning', 5*3)
# Apr 26 36 HRS
ActualData = updateDF (ActualData, '26/04/2018', sprint, 'Forritun: Upplýsingar greiðslumats', 7*3, 20, 20)
ActualData = updateDF (ActualData, '26/04/2018', sprint, 'Útlit: MaterialUI', 5*3)
# Apr 27 30 HRS
ActualData = updateDF (ActualData, '27/04/2018', sprint, 'Forritun: Nýtt greiðslumat', 10*2, 20, 20)
ActualData = updateDF (ActualData, '27/04/2018', sprint, 'Forritun: Prenta út skjöl', 10, 10, 10)
# Apr 28 27 HRS
ActualData = updateDF (ActualData, '28/04/2018', sprint, 'Forritun: Útbúa MockServer', 10)
ActualData = updateDF (ActualData, '28/04/2018', sprint, 'Prófanir: Útbúa notandaprófanir', 10)
ActualData = updateDF (ActualData, '28/04/2018', sprint, 'Prófanir: Einingaprófanir', 7)
# Tjékka hvort passar
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 6: 189

Framsetning gagna

In [25]:
# Burndown from sprint 6
makeMePieChartFromSprint(6)
plotBurndownChartFromSprint(6, 10)
plt.show()

Sprettur 7

Sjöundi spretturinn stóð yfir dagana 30. apríl til 6. maí áætlun samkvæmt. Í spretti 7 var svokallað feature freeze þar sem engin þróun var á virkni til þess að illa prófuð og vanhugsuð virkni væri ekki sett fram á síðustu stundu, enda hafði öll virkni verið útfærð í kerfinu. Sjöundi sprettur fór fyrst og fremst í að laga kerfið að þörfum hagsmunaaðila og tilvonandi notenda, en spretturinn hófst á notendaprófunum og fundum þar sem kerfið var sýnt og gerðar notendaprófanir á því. Fundurinn og prófanir komu vel út og það komu góðar tillögur að atriðum sem mátti bæta og laga. Teymið reyndi að mæta þessum kröfum og tillögum eins vel og hægt var og lauk svo spretti sínum með öðrum fundi við hagsmunaaðila og tilvonandi notendum þar sem lagfæringar höfðu verið gerðar út frá fyrri prófunum og samkæmt endurgjöf. Spretturinn fór því aðallega í uppsetningu upplýsinga, notendaviðmótshönnun, að bæta notendaupplifun og í útlitshönnun á kerfinu. Teymið vann 207 tíma sem er yfir 100% af vinnutíma miðað við áætlun.

Gögn sett inn

In [26]:
## SPRETTUR 7
sprint = 7

# APR 30 36 HRS
ActualData = updateDF (ActualData, '30/04/2018', sprint, 'Fundur við fyrirtæki', 3*3)
ActualData = updateDF (ActualData, '30/04/2018', sprint, 'Prófanir: Notendaprófanir', 3*3)
ActualData = updateDF (ActualData, '30/04/2018', sprint, 'Útlit: Lagfæra atriði notendaprófunar', 6*3)

# MAY 1 21 HRS
ActualData = updateDF (ActualData, '01/05/2018', sprint, 'Prófanir: Einingaprófanir', 5)
ActualData = updateDF (ActualData, '01/05/2018', sprint, 'Undirbúningur: Kynningarundirbúningur', 2*3 + 10)

# MAY 2 30 HRS
ActualData = updateDF (ActualData, '02/05/2018', sprint, 'Undirbúningur: Kynningarundirbúningur', 3*3)
ActualData = updateDF (ActualData, '02/05/2018', sprint, 'Forritun: Uppsetning', 3*3)
ActualData = updateDF (ActualData, '02/05/2018', sprint, 'Prófanir: Einingaprófanir', 4*3)

# MAY 3 36 HRS
ActualData = updateDF (ActualData, '03/05/2018', sprint, 'Forritun: Uppsetning', 2*3)
ActualData = updateDF (ActualData, '03/05/2018', sprint, 'Undirbúningur: Þróun gerviþjóns', 3*3)
ActualData = updateDF (ActualData, '03/05/2018', sprint, 'Forritun: Uppsetning', 3*3)
ActualData = updateDF (ActualData, '03/05/2018', sprint, 'Prófanir: Einingaprófanir', 4*3)

# MAY 4 36 HRS
ActualData = updateDF (ActualData, '04/05/2018', sprint, 'Fundur við fyrirtæki', 3*3)
ActualData = updateDF (ActualData, '04/05/2018', sprint, 'Prófanir: Notendaprófanir', 3*3)
ActualData = updateDF (ActualData, '04/05/2018', sprint, 'Forritun: Uppsetning', 6*3)

# MAY 5 33 HRS
ActualData = updateDF (ActualData, '05/05/2018', sprint, 'Forritun: Uppsetning', 5*3)
ActualData = updateDF (ActualData, '05/05/2018', sprint, 'Prófanir: Einingaprófanir', 3*3)
ActualData = updateDF (ActualData, '05/05/2018', sprint, 'Undirbúningur: Þróun gerviþjóns', 3*3)

# MAY 6 12 HRS
ActualData = updateDF (ActualData, '06/05/2018', sprint, 'Forritun: Uppsetning', 5*3)

# Tjékka hvort passar
print('Total hours spent on sprint ' + str(sprint) + ': ' + str(ActualData[ActualData['Sprint'] == sprint].Hours.sum()))
Total hours spent on sprint 7: 207
In [27]:
# Piechart from sprint 7
makeMePieChartFromSprint(7)
plt.show()