<commit_before>package main

import (
	"errors"
	"io"
	"log"
	"net"
	"sync"

	pb "github.com/taylorflatt/go-chat"
	context "golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

// The port the server is listening on.
const (
	port = ":12021"
)

type server struct{}

type Group struct {
	name      string
	ch        chan pb.ChatMessage
	clients   []string
	WaitGroup *sync.WaitGroup
}

type Client struct {
	name      string
	groups    []string
	ch        chan pb.ChatMessage
	WaitGroup *sync.WaitGroup
}

var lock = &sync.RWMutex{}
var clients map[string]*Client
var groups map[string]*Group

// AddClient adds a new client n to the server.
// It doesn't return anything.
func AddClient(n string) {

	lock.Lock()
	defer lock.Unlock()

	c := &Client{
		name:      n,
		ch:        make(chan pb.ChatMessage, 100),
		WaitGroup: &sync.WaitGroup{},
	}

	log.Print("[AddClient]: Registered client " + n)
	clients[n] = c
}

// AddGroup adds a new group to the server.
// It doesn't return anything.
func AddGroup(n string) {

	lock.Lock()
	defer lock.Unlock()

	g := &Group{
		name:      n,
		ch:        make(chan pb.ChatMessage, 100),
		WaitGroup: &sync.WaitGroup{},
	}

	log.Print("[AddGroup]: Added group " + g.name)
	groups[n] = g
	groups[n].WaitGroup.Add(1)
}

// ClientExists checks if a client exists on the server.
// It returns a bool value.
func ClientExists(name string) bool {

	lock.RLock()
	defer lock.RUnlock()
	for c := range clients {
		if c == name {
			return true
		}
	}

	return false
}

// GroupExists checks if a group exists on the server.
// It returns a bool value.
func GroupExists(gName string) bool {

	lock.RLock()
	defer lock.RUnlock()
	for g := range groups {
		if g == gName {
			return true
		}
	}

	return false
}

// InGroup checks whether a client is currently in a
// specific group.
// It returns a bool value.
func InGroup(n string) bool {

	for _, g := range groups {
		for _, c := range g.clients {
			if n == c {
				return true
			}
		}
	}

	return false
}

// RemoveClient will remove a client from the server as well as any
// groups that they are currently in.
// It returns an error.
func RemoveClient(name string) error {

	lock.Lock()
	defer lock.Unlock()

	if ClientExists(name) {
		delete(clients, name)
		log.Print("[RemoveClient]: Removed client " + name)
		if InGroup(name) {
			RemoveClientFromGroup(name)
		} else {
			log.Print("[RemoveClient]: " + name + " was not in any groups.")
			return nil
		}
	}

	return errors.New("[RemoveClient]: Client (" + name + ") doesn't exist")
}

// AddClientToGroup will add a client to a group.
// It doesn't return anything.
func AddClientToGroup(c string, g string) {

	//lock.Lock()
	//defer lock.Unlock()

	groups[g].WaitGroup.Add(1)
	defer groups[g].WaitGroup.Done()
<commit_msg>Added map initialization.<commit_after>package main

import (
	"errors"
	"io"
	"log"
	"net"
	"sync"

	pb "github.com/taylorflatt/go-chat"
	context "golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

// The port the server is listening on.
const (
	port = ":12021"
)

type server struct{}

type Group struct {
	name      string
	ch        chan pb.ChatMessage
	clients   []string
	WaitGroup *sync.WaitGroup
}

type Client struct {
	name      string
	groups    []string
	ch        chan pb.ChatMessage
	WaitGroup *sync.WaitGroup
}

var lock = &sync.RWMutex{}
var clients = make(map[string]*Client)
var groups = make(map[string]*Group)

// AddClient adds a new client n to the server.
// It doesn't return anything.
func AddClient(n string) {

	lock.Lock()
	defer lock.Unlock()

	c := &Client{
		name:      n,
		ch:        make(chan pb.ChatMessage, 100),
		WaitGroup: &sync.WaitGroup{},
	}

	log.Print("[AddClient]: Registered client " + n)
	clients[n] = c
}

// AddGroup adds a new group to the server.
// It doesn't return anything.
func AddGroup(n string) {

	lock.Lock()
	defer lock.Unlock()

	g := &Group{
		name:      n,
		ch:        make(chan pb.ChatMessage, 100),
		WaitGroup: &sync.WaitGroup{},
	}

	log.Print("[AddGroup]: Added group " + g.name)
	groups[n] = g
	groups[n].WaitGroup.Add(1)
}

// ClientExists checks if a client exists on the server.
// It returns a bool value.
func ClientExists(n string) bool {

	lock.RLock()
	defer lock.RUnlock()
	for c := range clients {
		if c == n {
			return true
		}
	}

	return false
}

// GroupExists checks if a group exists on the server.
// It returns a bool value.
func GroupExists(gName string) bool {

	lock.RLock()
	defer lock.RUnlock()
	for g := range groups {
		if g == gName {
			return true
		}
	}

	return false
}

// InGroup checks whether a client is currently in a
// specific group.
// It returns a bool value.
func InGroup(n string) bool {

	for _, g := range groups {
		for _, c := range g.clients {
			if n == c {
				return true
			}
		}
	}

	return false
}

// RemoveClient will remove a client from the server as well as any
// groups that they are currently in.
// It returns an error.
func RemoveClient(name string) error {

	// TODO: There is some deadlock here when a user attempts to quit
	// 		 the chat app with !exit.

	lock.Lock()
	defer lock.Unlock()

	if ClientExists(name) {
		delete(clients, name)
		log.Print("[RemoveClient]: Removed client " + name)
		if InGroup(name) {
			RemoveClientFromGroup(name)
		} else {
			log.Print("[RemoveClient]: " + name + " was not in any groups.")
			return nil
		}
	}

	return errors.New("[RemoveClient]: Client (" + name + ") doesn't exist")
}

// AddClientToGroup will add a client to a group.
// It doesn't return anything.
func AddClientToGroup(c string, g string) {

	//lock.Lock()
	//defer lock.Unlock()

	groups[g].WaitGroup.Add(1)
	defer groups[g].WaitGroup.Done()

{'fraction_non_alphanumeric': 0.12604456824512536, 'fraction_numerical': 0.004526462395543176, 'mean_word_length': 3.023109243697479, 'pattern_counts': {'":': 2, '<': 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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4285249', 'n_tokens_mistral': 2096, 'n_tokens_neox': 1969, 'n_words': 635}