ИЕП/К1 Септембар 2021

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

Први колоквијум у септембарском року 2021. године одржан је 17. септембра. Исти задаци дошли су и на првом колоквијуму 2022. године.

Поставка

Компанија уговара пројекте израде софтвера по наруџбини клијента. У компанији су запослени програмери и менаџери. У систему се води евиденција о сваком кораку рада (захтевима, додељеним пословима, развијеном коду). За сваки пројекат неког клијента, евидентирају се датум креирања, менаџер који је надлежан за њега као и сви кориснички захтеви. Пре него што пројекат отпочне, он мора бити испланиран (а након планирања статус пројекта постаје И). Планирање пројекта се састоји у томе да се за сваки кориснички захтев дефинише посао, као и колико ће израда тог посла трајати и колико ће програмера бити ангажовано на том послу. Након тога се одређују програмери и додељује им се ангажман на појединим пословима. Имплементација пројеката може да отпочне тек након што се пројекат испланира. Током имплементације, целокупан код који програмери развијају се такође евидентира у систему и то тако да је за сваки део кода дефинисано које корисничке захтеве имплементира.

KLIJENT (SifK, Naziv, Kontakt)
RADNIK (SifR, Ime)
MENADZER (SifR, Iskustvo)
PROGRAMER (SifR, Specijalnost)
PROJEKAT (SifP, Naziv, Status, Vrednost, Datum, SifK, SifR)
ZAHTEV (SifZ, Opis, SifP)
POSAO (SifJ, Trajanje, BrProgramera, SifP, SifZ)
ANGAZMAN (SifA, SifR, SifJ)
KOD (SifK, Kod)
IMPLEMENTIRA (SifK, SifZ)
  1. Навести по један пример сваког документа уколико би се за потребе наведене евиденције користила база података заснована на документима (mongoDB), али тако да модел искористи све предности нерелационог модела података.
  2. Саставити скрипт који користећи функцију за агрегацију (aggregation framework) враћа шифре и називе оних пројеката које имају вредност преко 1000, а при томе имају и више од 8 послова са трајањем преко 200.
  3. Саставити Map/Reduce посао који за сваки датум када је креиран бар један пројекат враћа информацију о просечном броју корисничких захтева.

1. задатак

Радник

{
    "_id": 1,
    "Ime": "Pera",
    // Радник - 1, Менаџер - 2, Оба - 3
    "Tip": 1,
    // Menadzer
    "Iskustvo": null,
    // Programer
    "Specijalnost": "Docker"
}

Пројекат

{
    "_id": 1,
    "Naziv": "Softverska kompanija",
    "Status": "I",
    "Vrednost": 10000,
    "Datum": "2022-03-03T20:00:00Z",
    // Klijent
    "Klijent": {
        "Naziv": "Microsoft",
        "Kontakt": "[email protected]"
    },
    "Menadzer": 4,
    // Posao
    "Poslovi": [
        {
            "Zahtev": 1,
            "Trajanje": 90,
            "BrProgramera": 5,
            // Angazman
            "Programeri": [1, 2, 3, 4, 5]
        }
    ],
    "Zahtevi": [1, 2, 3, 4]
}

Захтев

{
    "_id": 1,
    "Opis": "Tabela Implementira"
}

Код

{
    "_id": 1,
    "Kod": "int main() {...}",
    // Implementira
    "Zahtevi": [1, 2, 3, 4]
}

2. задатак

db.Projekat.aggregate([
    // Филтрирање пројеката са вредношћу мањом од 1000.
    {
        $match: {
            Vrednost: {
                $gt: 1000
            }
        }
    },
    // Дељење сваког пројекта тако да се сваки посао налази у одвојеном објекту.
    {
        $unwind: "$Poslovi"
    },
    // Избацивање послова са мање од 200 трајања.
    {
        $match: {
            "Poslovi.Trajanje": {
                $gt: 200
            }
        }
    },
    // Груписање пројеката назад са бројањем послова.
    {
        $group: {
            _id: "$_id",
            BrojPoslova: {
                $count: {}
            },
            Naziv: {
                $first: "$Naziv"
            }
        }
    },
    // Филтрирање пројеката са мање од 8 послова који имају преко 200 трајања.
    {
        $match: {
            BrojPoslova: {
                $gt: 8
            }
        }
    },
    // Враћање у траженом облику.
    {
        $project: {
            sifra: "$_id",
            naziv: "$Naziv"
        }
    }
]);

3. задатак

function map() {
    emit(this.Datum, {
        sum: this.Zahtevi.length,
        count: 1,
        avg: 0
    });
}

function reduce(key, values) {
    return {
        sum: Array.sum(values.map(v => v.sum)),
        count: Array.sum(values.map(v => v.count)),
        avg: 0
    };
}

function finalize(key, value) {
    value.avg = value.sum / value.count;
    return value;
}

db.Projekat.mapReduce(map, reduce, {out: 'k1_septembar_2021_c', finalize});

Тестирање

Решења изнад можете тестирати над следећом базом:

db.createCollection('Radnik');
db.createCollection('Projekat');
db.createCollection('Zahtev');
db.createCollection('Kod');
db.Projekat.insertMany([
    {
        _id: 1,
        Naziv: 'Softverska kompanija',
        Status: 'I',
        Vrednost: 10000,
        Datum: '2022-03-03T20:00:00Z',
        Klijent: {
            Naziv: 'Microsoft',
            Kontakt: '[email protected]'
        },
        Menadzer: 4,
        Poslovi: [
            {
                Zahtev: 1,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 2,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 3,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 4,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 5,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 6,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 7,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 8,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            },
            {
                Zahtev: 9,
                Trajanje: 201,
                BrProgramera: 5,
                Programeri: [1, 2, 3, 4, 5]
            }
        ],
        Zahtevi: [1, 2, 3, 4, 5, 6, 7, 8, 9]
    },
    // ...
]);
db.Radnik.insertMany([
    {_id: 1, Ime: 'Pera', Tip: 1, Iskustvo: null, Specijalnost: 'Docker'},
    {_id: 2, Ime: 'Mika', Tip: 2, Iskustvo: 2, Specijalnost: null},
    {_id: 3, Ime: 'Žika', Tip: 1, Iskustvo: null, Specijalnost: 'C#'},
    {_id: 4, Ime: 'Miloš', Tip: 2, Iskustvo: 10, Specijalnost: null},
    {_id: 5, Ime: 'Zaharije', Tip: 1, Iskustvo: null, Specijalnost: 'Docker'},
    {_id: 6, Ime: 'Jovan', Tip: 1, Iskustvo: null, Specijalnost: 'Python'}
]);
db.Zahtev.insertMany([
    {_id: 1, Opis: 'Tabela Klijent'},
    {_id: 2, Opis: 'Tabela Radnik'},
    {_id: 3, Opis: 'Tabela Menadzer'},
    {_id: 4, Opis: 'Tabela Programer'},
    {_id: 5, Opis: 'Tabela Projekat'},
    {_id: 6, Opis: 'Tabela Zahtev'},
    {_id: 7, Opis: 'Tabela Posao'},
    {_id: 8, Opis: 'Tabela Angazman'},
    {_id: 9, Opis: 'Tabela Kod'},
    {_id: 10, Opis: 'Tabela Implementira'}
]);
db.Kod.insertMany([
    {_id: 1, Kod: 'int main(void) {return 0;}', Zahtevi: [1, 2, 3, 4]},
    {_id: 2, Kod: 'def main():\n    print("Hello world")', Zahtevi: [5, 6, 7, 8]},
    {_id: 3, Kod: 'System.out.println("Hello world");', Zahtevi: [9, 10]}
]);