Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "strings"
- "sync"
- )
- // Player struct for storing player data.
- type Player struct {
- Name string
- GamesPlayed int
- AveragePoints float64
- }
- // Monitor for concurrent operations
- type Monitor struct {
- Players []Player
- mutex *sync.Mutex
- cond *sync.Cond
- currentSize int
- done bool
- }
- // ResultData struct for storing results.
- type ResultData struct {
- ResultingPlayer Player
- Efficiency float64
- Rank string
- }
- // Results array with mutual exclusion.
- type Results struct {
- results []ResultData
- mutex *sync.Mutex
- }
- func readData(fileName string) []Player {
- file, _ := ioutil.ReadFile(fileName)
- data := []Player{}
- _ = json.Unmarshal(file, &data)
- return data
- }
- func initializeMonitor(size int) Monitor {
- var Players = make([]Player, size)
- var mutex = sync.Mutex{}
- var cond = sync.NewCond(&mutex)
- var monitor = Monitor{Players, &mutex, cond, 0, false}
- return monitor
- }
- func initializeResults() Results {
- var results = []ResultData{}
- var mutex = sync.Mutex{}
- return Results{results, &mutex}
- }
- func (monitor *Monitor) insert(player Player) {
- monitor.mutex.Lock()
- for monitor.currentSize == len(monitor.Players) {
- monitor.cond.Wait()
- }
- monitor.Players[monitor.currentSize] = player
- monitor.currentSize++
- monitor.cond.Broadcast()
- monitor.mutex.Unlock()
- }
- func (monitor *Monitor) remove() Player {
- monitor.mutex.Lock()
- for monitor.currentSize == 0 {
- if monitor.done {
- monitor.cond.Broadcast()
- monitor.mutex.Unlock()
- return Player{}
- }
- monitor.cond.Wait()
- }
- var player = monitor.Players[monitor.currentSize-1]
- monitor.Players[monitor.currentSize-1] = Player{}
- monitor.currentSize--
- monitor.cond.Broadcast()
- monitor.mutex.Unlock()
- return player
- }
- func (results *Results) insertResult(result ResultData) {
- results.mutex.Lock()
- inserted := false
- for i, v := range results.results {
- if v.Efficiency < result.Efficiency {
- results.results = append(results.results, ResultData{})
- copy(results.results[i+1:], results.results[i:])
- results.results[i] = result
- inserted = true
- break
- }
- }
- if !inserted {
- results.results = append(results.results, result)
- }
- results.mutex.Unlock()
- }
- func performOperation(monitor *Monitor, results *Results, waiter *sync.WaitGroup) {
- defer waiter.Done()
- for !monitor.done || monitor.currentSize != 0 {
- player := monitor.remove()
- if player == (Player{}) {
- continue
- }
- result := player.operation()
- if result.Efficiency >= 30 {
- results.insertResult(result)
- }
- }
- }
- func (p Player) operation() ResultData {
- var efficiency float64 = float64(p.GamesPlayed/8) + p.AveragePoints
- var rank string
- switch {
- case efficiency < 10:
- rank = "Useless"
- case efficiency < 20:
- rank = "Role Player"
- case efficiency < 30:
- rank = "Starter"
- case efficiency < 40:
- rank = "Star"
- default:
- rank = "Superstar"
- }
- return ResultData{p, efficiency, rank}
- }
- func saveResults(results []ResultData, fileName string) error {
- file, err := os.Create(fileName)
- if err != nil {
- return err
- }
- defer file.Close()
- _, err = io.WriteString(file, fmt.Sprintf("| %21s | %12s | %14s | %10s | %11s |\n", "Name", "Games played", "Average points", "Efficiency", "Rank"))
- if err != nil {
- return err
- }
- _, err = io.WriteString(file, strings.Repeat("-", 84)+"\n")
- if err != nil {
- return err
- }
- for _, v := range results {
- _, err = io.WriteString(file, fmt.Sprintf("| %21s | %12d | %14.2f | %10.2f | %11s |\n", v.ResultingPlayer.Name, v.ResultingPlayer.GamesPlayed, v.ResultingPlayer.AveragePoints, v.Efficiency, v.Rank))
- if err != nil {
- return err
- }
- }
- return file.Sync()
- }
- //const fileName string = "IFF-7-1_GrabauskasM_L1_dat_1.json"
- const fileName string = "IFF-7-1_GrabauskasM_L1_dat_2.json"
- //const fileName string = "IFF-7-1_GrabauskasM_L1_dat_3.json"
- const resultFileName string = "IFF-7-1_GrabauskasM_L1_rez.txt"
- func main() {
- data := readData(fileName)
- monitor := initializeMonitor(len(data) / 2)
- results := initializeResults()
- waiter := sync.WaitGroup{}
- waiter.Add(5)
- for i := 0; i < 5; i++ {
- go performOperation(&monitor, &results, &waiter)
- }
- for _, v := range data {
- monitor.insert(v)
- }
- monitor.mutex.Lock()
- monitor.done = true
- monitor.cond.Broadcast()
- monitor.mutex.Unlock()
- waiter.Wait()
- err := saveResults(results.results, resultFileName)
- if err != nil {
- fmt.Println("Writing went wrong.")
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement