Skoči na vsebino

P2 - 2021/22 - DN08 Poleti v Planici - resitev Aljaz Starc

Vsebina Download link
Viri za vse teste viri.zip
Source resene naloge DN08.java
Naloga na eucilnici ucilnica.fri.uni-lj.si

Prepping for shitstorm

Vsi razni importi

import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Entity classes

Ker se naloga vlece tja v en dan sem si zelel, vsaj na dolg rok, poenostavit situacijo. Zato sem si naredil class-e za vsak ti. entity.

Tekmovalec
class Tekmovalec {
    public int      bib;
    public String   fullname;
    public String   club;
    public String   birthdate;
    public String   country;

    /**
     * 
     * @param bib - id tekmovalca
     * @param fullname - polno ime tekmovalca
     * @param club - ime kluba
     * @param birthdate - tekmovalcev datum rostva
     * @param country - drzava
     */
    public Tekmovalec (int bib, String fullname, String club, String birthdate, String country) {
        this.bib =          bib;
        this.fullname =     fullname;
        this.club =         club;
        this.birthdate =    birthdate;    
        this.country =      country;
    }

    /**
     * Get a player result from a provided list of results
     * 
     * @param results - lista razultatov iz katere naj izlocimo tekmovalcev rezultat
     * @return tekmovalcev rezultat
     */
    public Result getResultFrom (ArrayList<Result> results) {
        // https://www.baeldung.com/find-list-element-java#5-java-8-stream-api
        return results.stream().filter(res -> res.bib == this.bib).findAny().orElse(null);
    }

    /**
     * Get a player Mark from a provided list of marks
     * 
     * @param marks - lista tock iz katere naj izlocimo tekmovalceve ocene
     * @return tekmovalceve ocene
     */
    public Mark getMarkFrom (ArrayList<Mark> marks) {
        return marks.stream().filter(mark -> mark.bib == this.bib).findAny().orElse(null);
    }

    /**
     * Get points from given list of Mark objects
     *  if -1.0 the player was disqualified
     *  if  0.0 there is no Mark in given ArrayList
     * 
     * @param marks
     * @return
     */
    public Double getPointsFrom (ArrayList<Mark> marks) {
        Mark mark = this.getMarkFrom(marks);
        if (mark == null) return 0.0;
        return mark.getPoints();
    }

    /**
     * Get formatted string of points in given ArrayList
     *  if disqualified, retuns "DSQ  "
     *  if Mark not in list, returns "  -  "
     *  else returns the value formatted to ###.#
     * 
     * @param marks
     * @return
     */
    public String getPointStrFrom (ArrayList<Mark> marks) {
        Double points = this.getPointsFrom(marks);
        if (points == -1.0) return "DSQ  ";
        else if (points == 0.0) return "  -  ";
        else return String.format("%5.1f", points);
    }

    /**
     * Returns the calculated sum of points from both, first and second round.
     *  invluding the ramp, wind and other compensations
     * 
     * @param marks1
     * @param marks2
     * @return 
     */
    public Double getTotalPoints (ArrayList<Mark> marks1, ArrayList<Mark> marks2) {
        Double ptotal = 0.0;
        
        Double p1 = this.getPointsFrom(marks1);
        if (p1 != null && p1 > 0) ptotal += p1;

        Double p2 = this.getPointsFrom(marks2);
        if (p2 != null && p2 > 0) ptotal += p2;

        return ptotal;
    }


    public java.util.Date getBirthdayDate () throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy");
        return formatter.parse(this.birthdate.replace("SEP", "SEPT"));
    }
}
Result - rezultat
class Result {
    public Integer           bib;
    public Double           speed;
    public Double           distance;
    public Integer          gate;
    public Double           jump_points;
    public Double           wind_mps;
    public Double           wind_points;
    public Boolean          disqalified;
    public ArrayList<Mark>  marks;

    /**
     * 
     * @param bib - id tekmovalca
     * @param speed - hitrost skoka
     * @param distance - dolzina skoka
     * @param gate - ID vrat od koder je skakalec skocil
     * @param jump_points - pridobljene tocne
     * @param wind_mps - hitrost vetra
     * @param wind_points - modifikacija tock na podlagi hitrosti vetra
     * @param disqalified
     * @param marks - lista ocen iste serije kot ta rezultat
     */
    public Result (int bib, double speed, double distance, int gate, double jump_points, double wind_mps, double wind_points, Boolean disqalified, ArrayList<Mark> marks) {
        this.bib =          bib;
        this.speed =        speed;
        this.distance =     distance;
        this.gate =         gate;
        this.jump_points =  jump_points;
        this.wind_mps =     wind_mps;
        this.wind_points =  wind_points;
        this.disqalified =  disqalified;
        this.marks =        marks;
    }

    /**
     * Get a player Mark for this result
     * 
     * @return tekmovalceve ocene
     */
    public Mark getMark() {
        return this.marks.stream().filter(mark -> mark.bib == this.bib).findAny().orElse(null);
    }
}
Mark - ocene
class Mark {
    public Integer bib;
    public Double a;
    public Double b;
    public Double c;
    public Double d;
    public Double e;
    public Boolean disqualified;
    private ArrayList<Result> results;

    /**
     * 
     * @param bib - id tekmovalca
     * @param a - ocena sodnika a
     * @param b - ocena sodnika b
     * @param c - ocena sodnika c
     * @param d - ocena sodnika d
     * @param e - ocena sodnika
     * @param results - lista rezultatov iste serije kot ta Mark
     * e
     */
    public Mark (Integer bib, Double a, Double b, Double c, Double d, Double e, Boolean disqualified, ArrayList<Result> results) {
        this.bib = bib;
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.e = e;
        this.disqualified = disqualified;
        this.results = results;
    }

    /**
     * Get Result of this Mark
     * 
     * @return tekmovalceve ocene
     */
    public Result getResult () {
        return this.results.stream().filter(r -> r.bib == this.bib).findAny().orElse(null);
    }

    /**
     * Get the sum of points, without the max and min ones
     * 
     * If there is no result linked to this Mark, returns 0.0
     * If disqualified, returns -1.0
     * 
     * @return
     */
    public Double getPoints () {
        Result r = this.getResult();
        if (r == null) return 0.0;
        if (r.disqalified) return -1.0;

        Double finalPoints = DN08.FLYING_HILL_POINTS + 0.0;
        finalPoints += (r.distance - DN08.K_POINT) * DN08.METER_VALUE + r.jump_points + r.wind_points;

        ArrayList<Double> ocene = new ArrayList<Double>(Arrays.asList(this.a, this.b, this.c, this.d, this.e));
        Collections.sort(ocene);
        finalPoints += ocene.stream().skip(1).limit(3).reduce(0.0, Double::sum);

        return finalPoints;
    }
}

DN08

class DN08 {

    public static final int        K_POINT = 200;            // K-tocka letalnice
    public static final int        FLYING_HILL_POINTS = 120; // stevilo tock za dosezeno K-tocko
    public static final double     METER_VALUE = 1.2;        // faktor za dodatne tocke za vsak meter pod/nad K-tocko
    
    private static ArrayList<Tekmovalec> tekmovalci =    new ArrayList<Tekmovalec>();
    private static ArrayList<Result>     results1st =    new ArrayList<Result>();
    private static ArrayList<Result>     resultsFinal =  new ArrayList<Result>();
    private static ArrayList<Mark>       judMarks1st =   new ArrayList<Mark>();
    private static ArrayList<Mark>       judMarksFinal = new ArrayList<Mark>();

    public static void main (String[] a) throws Exception {
             if (a.length == 2 && a[0].equals("1")) part1(a[1]);
        else if (a.length == 3 && a[0].equals("2")) part2(a[1], a[2]);
        else if (a.length == 4 && a[0].equals("3")) part3(a[1], a[2], a[3]);
        else if (a.length == 4 && a[0].equals("4")) part4(a[1], a[2], a[3]);
        else if (a.length == 6 && a[0].equals("5")) part5(a[1], a[2], a[3], a[4], a[5]);
        else if (a.length == 8 && a[0].equals("6")) part6(a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
        else if (a.length == 4 && a[0].equals("7")) part7(a[1], a[2], a[3]);
        else if (a.length == 4 && a[0].equals("8")) part8(a[1], a[2], a[3]);
    }

Helper functions

Branje file-ov

Ker je blo lepo razvidno, da bo treba pri vsaki nalogi brat iz vsaj ene datoteke - in redundanta koda je zabita, saj se pojavi tu ali tam, a se jo je dobro cimbolj izogibati - sem si spisal funkcijo, kateri podam String filePath ki predstavlja path do datoteke, in ta mi vrne String[] array String-ov.

    public static String[] readFileToLines (String filePath) throws Exception {
        try (Stream<String> linesStream = Files.lines(Paths.get(filePath))) {
            List<String> lines = linesStream.collect(Collectors.toList());
            return lines.toArray(new String[0]);
        }
    }
Parsing startne liste
    public static void loadStartsList (String fileName, ArrayList<Tekmovalec> saveTo) throws Exception {
        String[] ls = readFileToLines(fileName);
        saveTo.clear();
        for (int i = 2; i + 5 <= ls.length; i += 6) {
            saveTo.add(new Tekmovalec(Integer.parseInt(ls[i]), ls[i + 1], ls[i + 2], ls[i + 3], ls[i + 4]));
        }
    }
Parsing liste rezultatov
    private static void loadResults (
        String loadFrom,
        ArrayList<Result> saveTo,
        ArrayList<Mark> marks
    ) throws Exception {
        saveTo.clear();
        Arrays.asList(readFileToLines(loadFrom)).stream().skip(1).forEach((String line) -> {
            String[] p = line.split(";");
            if (p[1].equals("DSQ")) saveTo.add(new Result(Integer.parseInt(p[0]), 0.0, -1.0, 0, 0.0, 0.0, 0.0, true, marks));
            else saveTo.add(new Result(
                Integer.parseInt(p[0]),
                Double.parseDouble(p[1]),
                Double.parseDouble(p[2]),
                Integer.parseInt(p[3]),
                p[4].equals("") ? 0.0 : Double.parseDouble(p[4]),
                Double.parseDouble(p[5]),
                Double.parseDouble(p[6]),
                false,
                marks
            ));
        });
    }
Parsing liste tockovanj
    private static void loadJudMarks (
        String loadFrom,
        ArrayList<Mark> saveTo,
        ArrayList<Result> results
    ) throws Exception {
        saveTo.clear();
        Arrays.asList(readFileToLines(loadFrom)).stream().skip(1).forEach((String line) -> {
            String[] p = line.split(";");

            if (p[1].equals("DSQ")) saveTo.add(new Mark(Integer.parseInt(p[0]), -1.0, -1.0, -1.0, -1.0, -1.0, true, results));
            else saveTo.add(new Mark(
                Integer.parseInt(p[0]),
                Double.parseDouble(p[1]),
                Double.parseDouble(p[2]),
                Double.parseDouble(p[3]),
                Double.parseDouble(p[4]),
                Double.parseDouble(p[5]),
                false,
                results
            ));
        });
    }
Zapisovanje podatkov v file

Tako kot pri branju iz file-ov, sem si spisal fukcijo kateri podam nekaj parametrov, pot do datoteke, vsebino, ter dolocilo, ki doloca naj bo vrstica append-ana na konec datoteke, ali naj prepise cez trenutno vsebino.

    public static void writeToFile(String writeTo, String content, Boolean append) {
        try { Files.writeString(Paths.get(writeTo), content + System.lineSeparator(), StandardOpenOption.CREATE, append ? StandardOpenOption.APPEND : StandardOpenOption.TRUNCATE_EXISTING); }
        catch (Exception e) { /* EXCEPTION OCCURED, we - the naughty, lazy, bastards that we are - ignore it >:} */ }
    }

Naloga 1

    public static void part1 (String fileName) throws Exception {
        loadStartsList(fileName, tekmovalci);
        System.out.println("Start List 1st Round:\nBIB NAME                      (NSA)  [DATE OF BIRTH, CLUB]");
        for (Tekmovalec t : tekmovalci) System.out.format("%3d %-25s (%s)  [%11s, %s]\n", t.bib, t.fullname, t.country, t.birthdate, t.club);
    }

Naloga 2

    public static void part2 (String startFile, String resultsFile) throws Exception {
        loadStartsList(startFile, tekmovalci);
        loadResults(resultsFile, results1st, judMarks1st);
        System.out.println("Results first round:\nBIB NAME                      (NSA)  [DATE OF BIRTH, CLUB]                          DISTANCE [m]");
        for (Tekmovalec t : tekmovalci) {
            Result r = t.getResultFrom(results1st);
            String p1 = String.format("%3d %-25s (%s)  [%11s, %s]", t.bib, t.fullname, t.country, t.birthdate, t.club);
            String p2 = r.disqalified ? "Disqualified" : String.format("%5.1f", r.distance);
            System.out.format("%-83s %s\n", p1, p2);
        }
    }

Naloga 3

    public static void part3 (String startFile, String resultsFile, String resultsFinalFile) throws Exception {
        loadStartsList(startFile, tekmovalci);
        loadResults(resultsFile, results1st, judMarks1st);
        loadResults(resultsFinalFile, resultsFinal, judMarksFinal);

        System.out.println("Results final round:\nBIB NAME                      (NSA)  [DATE OF BIRTH, CLUB]                          DISTANCE [m]  (DISTANCE [m])");
        for (Tekmovalec t : tekmovalci) {
            String p1 = String.format("%3d %-25s (%s)  [%11s, %s]", t.bib, t.fullname, t.country, t.birthdate, t.club);

            String p2, p3 = "";
            Result rFin = t.getResultFrom(resultsFinal);
            Result r1st = t.getResultFrom(results1st);

            if (rFin == null) p2 = "Not qualified";
            else if (rFin.disqalified) p2 = "Disqualified";
            else p2 = String.format("%5.1f", rFin.distance);

            if (r1st == null) p3 = "";
            else if (r1st.disqalified) p2 = "Disqualified";
            else p3 = String.format("(%5.1f)", r1st.distance);

            System.out.format("%-83s %-13s %s\n", p1, p2, p3);
        }
    }

Naloga 4

    public static void part4 (String startFile, String resultsFile, String judgesMarksFile) throws Exception {
        loadStartsList(startFile, tekmovalci);
        loadResults(resultsFile, results1st, judMarks1st);
        loadJudMarks(judgesMarksFile, judMarks1st, results1st);

        System.out.println("Points first round:\nBIB NAME                      (NSA)  POINTS");
        tekmovalci.forEach(t -> {
            System.out.format(
                "%3d %-25s (%s)  %s\n",
                t.bib,
                t.fullname,
                t.country,
                t.getPointStrFrom(judMarks1st)
            );
        });
    }

Naloga 5

    public static void part5 (
        String startFile,
        String resultsFile1,
        String judgesMarksFile1,
        String resultsFile2,
        String judgesMarksFile2
    ) throws Exception {
        loadStartsList(startFile, tekmovalci);
        loadResults(resultsFile1, results1st, judMarks1st);
        loadResults(resultsFile2, resultsFinal, judMarksFinal);
        loadJudMarks(judgesMarksFile1, judMarks1st, results1st);
        loadJudMarks(judgesMarksFile2, judMarksFinal, resultsFinal);
        
        System.out.println("Points final round:\nBIB NAME                      (NSA)  POINTS (1st)  POINTS (final)  TOTAL");
        tekmovalci.forEach(t -> {
            System.out.format(
                "%3d %-25s (%s)  %5s         %5s           %5s\n",
                t.bib,
                t.fullname,
                t.country,
                t.getPointStrFrom(judMarks1st),
                t.getPointStrFrom(judMarksFinal),
                t.getTotalPoints(judMarks1st, judMarksFinal) > 0 ? String.format("%5.1f", t.getTotalPoints(judMarks1st, judMarksFinal)) : "  -  "
            );
        });
    }

Naloga 6

{ insert harmful disease here } od naloge. Bi optimiziral, ce bi imel se kaj volje - a verjamem da vsi vemo da je nihce nima.

    public static void part6 (
        String start1File,
        String res1File,
        String judMarks1File,
        String res2File,
        String judMarks2File,
        String izhodStarts,
        String izhodResults
    ) throws Exception {
        loadStartsList(start1File, tekmovalci);
        loadResults(res1File, results1st, judMarks1st);
        loadResults(res2File, resultsFinal, judMarksFinal);
        loadJudMarks(judMarks1File, judMarks1st, results1st);
        loadJudMarks(judMarks2File, judMarksFinal, resultsFinal);

        ArrayList<Tekmovalec> tekmovalciSorted = new ArrayList<Tekmovalec>(tekmovalci);
        tekmovalciSorted.sort((Tekmovalec t0, Tekmovalec t1) -> {
            Double t0p = t0.getPointsFrom(judMarks1st);
            Double t1p = t1.getPointsFrom(judMarks1st);
            if (t0p < t1p) return 1;
            else if (t0p > t1p) return -1;
            else {
                Double t0d = t0.getResultFrom(results1st).distance;
                Double t1d = t1.getResultFrom(results1st).distance;
                if (t0d < t1d) return 1;
                if (t0d > t1d) return -1;
                else return 0;
            }
        });


        Tekmovalec[] tekms2s = tekmovalciSorted.stream()
            .filter((Tekmovalec t) -> !t.getResultFrom(results1st).disqalified)
            .limit(30)
            .toArray(a -> new Tekmovalec[a]);

        ArrayList<String> startsLines = new ArrayList<String>();
        int rankPrevious = 1;
        for (int i = 0; i < tekms2s.length; i++) {
            Tekmovalec t1 = tekms2s[i];

            Double points = t1.getPointsFrom(judMarks1st);
            int rankNow = points.equals(tekms2s[ i==0 ? 0 : i-1].getPointsFrom(judMarks1st)) ? rankPrevious : i + 1;
            rankPrevious = rankNow;

            Double behind = tekms2s[0].getPointsFrom(judMarks1st) - points;
            startsLines.add(String.format(
                "%d;%d;%s;%s;%5.1f;%d;%.1f",
                tekms2s.length - i,
                t1.bib,
                t1.fullname,
                t1.country,
                points,
                rankNow,
                behind
            ));
        }
        Collections.reverse(startsLines);

        writeToFile(izhodStarts, "START ORD.;BIB;NAME;NSA;POINTS;RANK;BEHIND POINTS", false);
        startsLines.forEach((String s) -> writeToFile(izhodStarts, s, true));



        ArrayList<Tekmovalec> tekSortedByTotal = new ArrayList<Tekmovalec>(tekmovalci);
        ArrayList<String> resultsLines = new ArrayList<String>();
        Tekmovalec[] resultsTotalTekmovalci = tekSortedByTotal.stream().sorted((Tekmovalec t0, Tekmovalec t1) -> {
            Double t0p = t0.getTotalPoints(judMarks1st, judMarksFinal);
            Double t1p = t1.getTotalPoints(judMarks1st, judMarksFinal);
            if ( t0p < t1p) return 1;
            else if (t0p > t1p) return -1;
            else {
                if (t0p > 0.0) return 0;
                if (t0.bib < t1.bib) return 1;
                if (t0.bib > t1.bib) return -1;
                return 0;
            }
        }).toArray(a -> new Tekmovalec[a]);

        int resultsTotalRankPrev = 1;
        for (int i=0; i<resultsTotalTekmovalci.length;i++) {
            Tekmovalec t = resultsTotalTekmovalci[i];

            Result r1raw = t.getResultFrom(results1st);
            Result r2raw = t.getResultFrom(resultsFinal);

            String dist1 = "DSQ";
            String dist2 = "-";
            String points1 = "-";
            String points2 = "-";

            if (!r1raw.disqalified) {
                dist1 = String.format("%.1f", r1raw.distance);
                points1 = String.format("%.1f", t.getPointsFrom(judMarks1st));   
                if (r2raw == null) dist2 = "-";
                else if (r2raw.disqalified) dist2 = "DSQ";
                else if (!r2raw.disqalified) {
                    dist2 = String.format("%.1f", r2raw.distance);
                    points2 = String.format("%.1f", t.getPointsFrom(judMarksFinal));
                }
            }

            Double points = t.getTotalPoints(judMarks1st, judMarksFinal);
            int rankNow = points.equals(resultsTotalTekmovalci[ i==0 ? 0 : i-1].getTotalPoints(judMarks1st, judMarksFinal)) ? resultsTotalRankPrev : i + 1;
            resultsTotalRankPrev = rankNow;

            resultsLines.add(String.format(
                "%d;%d;%s;%s;%s;%s;%s;%s;%.1f",
                rankNow,
                t.bib,
                t.fullname,
                t.country,
                dist1,
                dist2,
                points1,
                points2,
                t.getTotalPoints(judMarks1st, judMarksFinal)
            ));
        }

        writeToFile(izhodResults, "RANK;BIB;NAME;NSA;DIST-1;DIST-2;POINTS-1;POINTS-2;TOTAL", false);
        resultsLines.forEach((String s) -> writeToFile(izhodResults, s, true));
    }

Naloga 7

    public static void part7 (String startFile, String resultsFile, String resultsFinalFile) throws Exception {
        loadStartsList(startFile, tekmovalci);
        loadResults(resultsFile, results1st, judMarks1st);
        loadResults(resultsFinalFile, resultsFinal, judMarksFinal);

        List<Tekmovalec> kpointTekmovalci = tekmovalci.stream()
            .filter((Tekmovalec t) -> {
                try {
                    if (t.getResultFrom(results1st) != null && (
                        t.getResultFrom(results1st).distance >= DN08.K_POINT ||
                        t.getResultFrom(resultsFinal).distance >= DN08.K_POINT
                    )) return true;
                } catch (Exception e) { /* Neomo nc nrdili, ker smo leni :> */ }
                return false;
            }).sorted((Tekmovalec t0, Tekmovalec t1) -> {
                try { return t0.getBirthdayDate().compareTo(t1.getBirthdayDate()) * -1; }
                catch (Exception e) { return 0; }
            }).collect(Collectors.toList());


        if (kpointTekmovalci.size() == 0) { System.out.println("All flights are below K-point."); }
        else {
            Tekmovalec najmlajsi = kpointTekmovalci.get(0);

            kpointTekmovalci.stream()
                .filter((Tekmovalec t) -> {
                    try { return t.getBirthdayDate().equals(najmlajsi.getBirthdayDate()); }
                    catch (Exception e) { return false; }
                })
                .map((Tekmovalec t) -> t.fullname)
                .forEach(System.out::println);
        }
    }

Naloga 8

    public static void part8 (String startFile, String marks1File, String marks2File) throws Exception {
        loadStartsList(startFile, tekmovalci);
        loadJudMarks(marks1File, judMarks1st, results1st);
        loadJudMarks(marks2File, judMarksFinal, resultsFinal);

        Mark[] marks = Stream.concat(judMarks1st.stream(), judMarksFinal.stream()).filter((Mark m) -> !m.disqualified).toArray(mark -> new Mark[mark]);

        // vem da je nonsense, se da lepse nrdit, se mi trenutno ne da ke imam pun kufr te jave <3
        // Imamo 5 itemov (5 sodnikov);
        //      vsak item ima dva property-ja;
        //          prvi predstavlja "indeks crke sodnika" (65 + jm[i][0])
        //          drugi predstavlja sestevek tock
        Double[][] jm = new Double[][]{{ 0.0, 0.0 }, { 1.0, 0.0 }, { 2.0, 0.0 }, { 3.0, 0.0 }, { 4.0, 0.0 }};

        for (Mark m: marks) {
            jm[0][1] += m.a;
            jm[1][1] += m.b;
            jm[2][1] += m.c;
            jm[3][1] += m.d;
            jm[4][1] += m.e;
        }

        Double[] min = Stream.of(jm).sorted((Double[] a0, Double[] a1) -> a0[1].compareTo(a1[1])).findFirst().orElseThrow(IllegalStateException::new);
        Double[] max = Stream.of(jm).sorted((Double[] a0, Double[] a1) -> a0[1].compareTo(a1[1]) * -1).findFirst().orElseThrow(IllegalStateException::new);

        System.out.format("Best marks:  %s (%.1f)\n", (char) (max[0].intValue() + 65), max[1] / marks.length);
        System.out.format("Worst marks: %s (%.1f)\n", (char) (min[0].intValue() + 65), min[1] / marks.length);
    }
}

Zadnja posodobitev: May 9, 2022