<commit_before>package data

import (
	"time"
)

// The available announcement types.
const (
	AnnouncementTypeText       = 0 // just informative
	AnnouncementTypeFullOff    = 1 // no classes at all
	AnnouncementTypeBreakStart = 2 // start of a break (inclusive of that day!)
	AnnouncementTypeBreakEnd   = 3 // end of a break (exclusive of that day!)
)

// A RecurFrequency describes how often an event recurs.
type RecurFrequency int

// Define the default RecurFrequencies.
const (
	RecurFrequencyDaily RecurFrequency = iota
	RecurFrequencyWeekly
	RecurFrequencyMonthly
	RecurFrequencyYearly
)

// An EventTagType describes the type of an event tag.
type EventTagType int

// The available event tags.
const (
	EventTagReserved EventTagType = iota
	EventTagDescription
	EventTagHomework
	EventTagTermID
	EventTagClassID
	EventTagOwnerID
	EventTagOwnerName
	EventTagDayNumber
	EventTagBlock
	EventTagBuildingName
	EventTagRoomNumber
)

// An Event is an event on a user's calendar. It could be from their schedule, homework, or manually added.
type Event struct {
	ID        int                          `json:"id"`
	Name      string                       `json:"name"`
	Start     int                          `json:"start"`
	End       int                          `json:"end"`
	RecurRule *RecurRule                   `json:"recurRule"`
	Tags      map[EventTagType]interface{} `json:"tags"`
	Source    int                          `json:"source"`
	UserID    int                          `json:"userId"`
}

// An OffBlock is a period of time that's marked off on a calendar, such as a holiday.
type OffBlock struct {
	StartID   int       `json:"startId"`
	EndID     int       `json:"endId"`
	Start     time.Time `json:"-"`
	End       time.Time `json:"-"`
	StartText string    `json:"start"`
	EndText   string    `json:"end"`
	Name      string    `json:"name"`
	Grade     int       `json:"grade"`
}

// A RecurRule struct contains information about how an event recurs. Inspired by the iCal RRULE system.
type RecurRule struct {
	ID          int            `json:"id"`
	EventID     int            `json:"eventId"`
	Frequency   RecurFrequency `json:"frequency"`
	Interval    int            `json:"interval"`
	ByDayString string         `json:"-"`
	ByDay       []time.Weekday `json:"byDay"`
	ByMonthDay  int            `json:"byMonthDay"`
	ByMonth     time.Month     `json:"byMonth"`
	UntilString string         `json:"until"`
	Until       time.Time      `json:"-"`
}

// CalculateTimes returns a list of all times the given event will take place, using its RecurRule information.
func (e *Event) CalculateTimes(until time.Time) []time.Time {
	eventStartTime := time.Unix(int64(e.Start), 0)

	eventTimes := []time.Time{}

	// obviously it has to happen at least once
	eventTimes = append(eventTimes, eventStartTime)

	if e.RecurRule != nil {
		currentTime := eventStartTime

		for currentTime.Before(until) {
			years := 0
			months := 0
			days := 0

			if e.RecurRule.Frequency == RecurFrequencyDaily {
				days = 1
			} else if e.RecurRule.Frequency == RecurFrequencyWeekly {
				days = 7
			} else if e.RecurRule.Frequency == RecurFrequencyMonthly {
				months = 1
			} else if e.RecurRule.Frequency == RecurFrequencyYearly {
				years = 0
			}

			years *= e.RecurRule.Interval
			months *= e.RecurRule.Interval
			days *= e.RecurRule.Interval

			currentTime = currentTime.AddDate(years, months, days)

			if e.RecurRule.UntilString != "" {
				ruleUntil := e.RecurRule.Until<commit_msg>fix yearly recurring events being broken<commit_after>package data

import (
	"time"
)

// The available announcement types.
const (
	AnnouncementTypeText       = 0 // just informative
	AnnouncementTypeFullOff    = 1 // no classes at all
	AnnouncementTypeBreakStart = 2 // start of a break (inclusive of that day!)
	AnnouncementTypeBreakEnd   = 3 // end of a break (exclusive of that day!)
)

// A RecurFrequency describes how often an event recurs.
type RecurFrequency int

// Define the default RecurFrequencies.
const (
	RecurFrequencyDaily RecurFrequency = iota
	RecurFrequencyWeekly
	RecurFrequencyMonthly
	RecurFrequencyYearly
)

// An EventTagType describes the type of an event tag.
type EventTagType int

// The available event tags.
const (
	EventTagReserved EventTagType = iota
	EventTagDescription
	EventTagHomework
	EventTagTermID
	EventTagClassID
	EventTagOwnerID
	EventTagOwnerName
	EventTagDayNumber
	EventTagBlock
	EventTagBuildingName
	EventTagRoomNumber
)

// An Event is an event on a user's calendar. It could be from their schedule, homework, or manually added.
type Event struct {
	ID        int                          `json:"id"`
	Name      string                       `json:"name"`
	Start     int                          `json:"start"`
	End       int                          `json:"end"`
	RecurRule *RecurRule                   `json:"recurRule"`
	Tags      map[EventTagType]interface{} `json:"tags"`
	Source    int                          `json:"source"`
	UserID    int                          `json:"userId"`
}

// An OffBlock is a period of time that's marked off on a calendar, such as a holiday.
type OffBlock struct {
	StartID   int       `json:"startId"`
	EndID     int       `json:"endId"`
	Start     time.Time `json:"-"`
	End       time.Time `json:"-"`
	StartText string    `json:"start"`
	EndText   string    `json:"end"`
	Name      string    `json:"name"`
	Grade     int       `json:"grade"`
}

// A RecurRule struct contains information about how an event recurs. Inspired by the iCal RRULE system.
type RecurRule struct {
	ID          int            `json:"id"`
	EventID     int            `json:"eventId"`
	Frequency   RecurFrequency `json:"frequency"`
	Interval    int            `json:"interval"`
	ByDayString string         `json:"-"`
	ByDay       []time.Weekday `json:"byDay"`
	ByMonthDay  int            `json:"byMonthDay"`
	ByMonth     time.Month     `json:"byMonth"`
	UntilString string         `json:"until"`
	Until       time.Time      `json:"-"`
}

// CalculateTimes returns a list of all times the given event will take place, using its RecurRule information.
func (e *Event) CalculateTimes(until time.Time) []time.Time {
	eventStartTime := time.Unix(int64(e.Start), 0)

	eventTimes := []time.Time{}

	// obviously it has to happen at least once
	eventTimes = append(eventTimes, eventStartTime)

	if e.RecurRule != nil {
		currentTime := eventStartTime

		for currentTime.Before(until) {
			years := 0
			months := 0
			days := 0

			if e.RecurRule.Frequency == RecurFrequencyDaily {
				days = 1
			} else if e.RecurRule.Frequency == RecurFrequencyWeekly {
				days = 7
			} else if e.RecurRule.Frequency == RecurFrequencyMonthly {
				months = 1
			} else { // if e.RecurRule.Frequency == RecurFrequencyYearly {
				years = 1
			}

			years *= e.RecurRule.Interval
			months *= e.RecurRule.Interval
			days *= e.RecurRule.Interval

			currentTime = currentTime.AddDate(years, months, days)

			if e.RecurRule.UntilString != "" {
				ruleUntil := e.RecurRule.Until
{'fraction_non_alphanumeric': 0.09312606959498003, 'fraction_numerical': 0.003993154592127781, 'mean_word_length': 2.633678756476684, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3550429', 'n_tokens_mistral': 2270, 'n_tokens_neox': 2071, 'n_words': 642}