dzhw / zofar

10 stars 1 forks source link

calendar: function for checking if calendar is filled partially #483

Closed andreaschu closed 2 years ago

andreaschu commented 2 years ago

As a researcher I want to identify satisfizing behavior meaning to check if at least the half of all months of the calendar are filled with episodes.

christian-fr commented 2 years ago

    /** [REVIEW][TODO]
     * calls countEpisodesRatioHelper {@link #countEpisodesRatioHelper(com.google.gson.JsonArray,String,String)}; returns a float value representing the portion of a given time period that is filled with episode data (calculated on the level of days)
     * @param data input JSON object with episodes
     * @param rangeStart start date of the time period that is being considered
     * @param rangeStop end date of the time period that is being considered
     * @return ratio float value (range 0 to 1), returns 0 if data is empty or no rangeStart or rangeStop is given
     * @throws ParseException
     */
    public synchronized final float countEpisodesRatio(final JsonArray data,final String rangeStart, final String rangeStop) throws ParseException {
        System.out.println("data : "+data);
        System.out.println("rangeStart : "+rangeStart);
        System.out.println("rangeStop : "+rangeStop);

        if (data == null)
            return 0;
        if (data.size() == 0)
            return 0;
        if (rangeStart == null)
            return 0;
        if (rangeStop == null)
            return 0;

        final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

        Date rangeStartDate = null;
        Date rangeEndDate = null;
        if (rangeStart != null)
            rangeStartDate = format.parse(rangeStart);
        if (rangeStop != null)
            rangeEndDate = format.parse(rangeStop);

        return this.countEpisodesRatioHelper(data,rangeStartDate,rangeEndDate);
    }

    /** [REVIEW][TODO]
     * helper function, returns a float value representing the portion of a given time period that is filled with episode data (calculated on the level of days)
     * @param data input JSON object with episodes
     * @param rangeStart start date of the time period that is being considered
     * @param rangeStop end date of the time period that is being considered
     * @return ratio float value (range 0 to 1), returns 0 if data is empty or no rangeStart or rangeStop is given
     * @throws ParseException
     */
    private synchronized final float countEpisodesRatioHelper(final JsonArray data,final Date rangeStart, final Date rangeStop) throws ParseException {
        if (data == null)
            return 0;
        if (data.size() == 0)
            return 0;
        if (rangeStart == null)
            return 0;
        if (rangeStop == null)
            return 0;

        final Set<Date> hasEpisodes = new HashSet<Date>();
        final Set<Date> allDaysInCalendar = new HashSet<Date>();

        final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

        final Iterator<JsonElement> it = data.iterator();
        while (it.hasNext()) {
            final JsonElement tmp = it.next();
            if (!tmp.isJsonObject())
                continue;
            if (tmp.isJsonNull())
                continue;
            final JsonObject json = (JsonObject) tmp;
            if (!json.has("startDate"))
                continue;
            if (!json.has("endDate"))
                continue;
            if (json.get("startDate").isJsonNull())
                continue;
            if (json.get("endDate").isJsonNull())
                continue;
            String startDateStr = json.get("startDate").getAsString();
            startDateStr = startDateStr.substring(0, startDateStr.indexOf('T')) + "T01:00:00.000Z";
            final Date currentStartDate = format.parse(startDateStr);
            String endDateStr = json.get("endDate").getAsString();
            endDateStr = endDateStr.substring(0, endDateStr.indexOf('T')) + "T01:00:00.000Z";
            final Date currentEndDate = format.parse(endDateStr);

            final Calendar episodeStartCal = Calendar.getInstance();
            episodeStartCal.setTime(currentStartDate);

            final Calendar episodeStopCal = Calendar.getInstance();
            episodeStopCal.setTime(currentEndDate);

            for (Calendar lft = episodeStartCal; (lft.before(episodeStopCal) || lft.equals(episodeStopCal)); lft.add(Calendar.DAY_OF_YEAR, 1)) {
                final Date xx = lft.getTime();
                if (!hasEpisodes.contains(xx)) {
                    hasEpisodes.add(xx);
                }
            }
        }
        final Calendar startCal = Calendar.getInstance();
        startCal.setTime(rangeStart);
        startCal.set(Calendar.HOUR_OF_DAY, 1);
        final Calendar endCal = Calendar.getInstance();
        endCal.setTime(rangeStop);
        endCal.set(Calendar.HOUR_OF_DAY, 1);
        for (Calendar lft = startCal; (lft.before(endCal) || lft.equals(endCal)); lft.add(Calendar.DAY_OF_YEAR, 1)) {
            final Date xx = lft.getTime();
            allDaysInCalendar.add(xx);
            }
        // System.out.println(hasEpisodes.size());
        // System.out.println(allDaysInCalendar.size());
        final float ratio = (float) hasEpisodes.size() / allDaysInCalendar.size(); 
        // System.out.println((float) hasEpisodes.size() / allDaysInCalendar.size());

        return ratio;
        }

    /** [REVIEW][TODO]
     * calls countEpisodesRatioHelper {@link #countEpisodesRatioHelper(com.google.gson.JsonArray,String,String)}; returns a float value representing the portion of a given time period that is filled with episode data (calculated on the level of days)
     * @param data input JSON object with episodes
     * @return ratio float value (range 0 to 1), returns 0 if data is empty or no rangeStart or rangeStop is given
     * @throws ParseException
     */
    public synchronized final float countEpisodesRatio(final JsonArray data) throws ParseException {
        if (data == null)
            return 0;
        if (data.size() == 0)
            return 0;

        final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        Date minStartDate = null;
        Date maxEndDate = null;

        final Iterator<JsonElement> it = data.iterator();
        while (it.hasNext()) {
            final JsonElement tmp = it.next();
            if (!tmp.isJsonObject())
                continue;
            if (tmp.isJsonNull())
                continue;
            final JsonObject json = (JsonObject) tmp;
            if (!json.has("startDate"))
                continue;
            if (!json.has("endDate"))
                continue;
            String startDateStr = json.get("startDate").getAsString();
            startDateStr = startDateStr.substring(0, startDateStr.indexOf('T')) + "T00:00:00.000Z";
            final Date currentStartDate = format.parse(startDateStr);
            if (minStartDate == null)
                minStartDate = currentStartDate;
            else if (currentStartDate.before(minStartDate))
                minStartDate = currentStartDate;

            String endDateStr = json.get("endDate").getAsString();
            endDateStr = endDateStr.substring(0, endDateStr.indexOf('T')) + "T00:00:00.000Z";
            final Date currentEndDate = format.parse(endDateStr);
            if (maxEndDate == null)
                maxEndDate = currentEndDate;
            else if (currentEndDate.after(maxEndDate))
                maxEndDate = currentEndDate;
        }
        return this.countEpisodesRatioHelper(data,minStartDate,maxEndDate);
    }
christian-fr commented 2 years ago

@vdick @dzhwmeisner Please review the code and, if it turns out to be OK, add it to the FunctionProvider

christian-fr commented 2 years ago

Code review is done, new function is implemented in function provider.