package main import ( "encoding/json" "fmt" "math" "net/http" "os" "time" ) type CommitsResponse struct { Contestant1RequiredCommits float64 `json:"contestant_1_required_commits"` } // Function to fetch the user's commit count func getCommitCount(username string) (int, error) { currentYear := time.Now().Year() url := fmt.Sprintf("https://api.github.com/search/commits?q=author:%s+committer-date:%d-01-01..%d-12-31", username, currentYear, currentYear) // Retrieve the GitHub token from environment variables githubToken := os.Getenv("GITHUB_TOKEN") if githubToken == "" { return 0, fmt.Errorf("GITHUB_TOKEN environment variable is not set") } // Create a new HTTP request req, err := http.NewRequest("GET", url, nil) if err != nil { return 0, err } // Add necessary headers req.Header.Add("Accept", "application/vnd.github.cloak-preview") req.Header.Add("Authorization", "Bearer "+githubToken) // Perform the request client := &http.Client{} resp, err := client.Do(req) if err != nil { return 0, err } defer resp.Body.Close() // Check if the response status code is 200 OK if resp.StatusCode != http.StatusOK { return 0, fmt.Errorf("GitHub API returned status: %s", resp.Status) } // Parse the response body var result struct { TotalCount int `json:"total_count"` } if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return 0, err } return result.TotalCount, nil } // Calculate remaining days in the year func daysUntilYearEnd() int { today := time.Now() endOfYear := time.Date(today.Year(), 12, 31, 23, 59, 59, 0, today.Location()) return int(endOfYear.Sub(today).Hours() / 24) } // Calculate required commits per day func calculateRequiredCommits(commits1, commits2 int, remainingDays int) (float64) { expectedCommits2 := float64(commits2) + float64(remainingDays) diffForContestant1 := math.Max(expectedCommits2-float64(commits1), 0) requiredCommitsPerDay1 := diffForContestant1 / float64(remainingDays) return requiredCommitsPerDay1 } // HTTP handler for the API func calculateCommitsHandler(w http.ResponseWriter, r *http.Request) { // Get commit counts for both contestants commits1, err := getCommitCount("user1") // Replace with Contestant 1's GitHub username if err != nil { http.Error(w, fmt.Sprintf("Failed to fetch commits for Contestant 1: %s", err), http.StatusInternalServerError) return } commits2, err := getCommitCount("user2") // Replace with Contestant 2's GitHub username if err != nil { http.Error(w, fmt.Sprintf("Failed to fetch commits for Contestant 2: %s", err), http.StatusInternalServerError) return } // Calculate required commits remainingDays := daysUntilYearEnd() requiredCommits1 := calculateRequiredCommits(commits1, commits2, remainingDays) // Prepare response response := CommitsResponse{ Contestant1RequiredCommits: math.Round(requiredCommits1*100) / 100, // Round to 2 decimal places } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } func main() { // Set up routes http.HandleFunc("/calculate", calculateCommitsHandler) // Start the server fmt.Println("Starting server on port 8080...") http.ListenAndServe(":8080", nil) }