<commit_before>package main

import (
	"bufio"
	"log"
	"net"
	)

type EchoClient struct {
	conn net.Conn
	reader *bufio.Reader
	writer *bufio.Writer
	writeChannel chan string
	closeChannel chan bool
}

func NewEchoClient(conn net.Conn) (e *EchoClient) {
	e = new(EchoClient)
	e.conn = conn
	e.reader = bufio.NewReader(conn)
	e.writer = bufio.NewWriter(conn)
	e.writeChannel = make(chan string)
	e.closeChannel = make(chan bool)
	return
}

func readLines(e *EchoClient) {
	for {
		line, err := e.reader.ReadString('\n')
		if err != nil {
			log.Print("readLines:", err)
			close(e.writeChannel)
			return
		}
		select {
		case e.writeChannel <- line:
			continue
		case <- e.closeChannel:
			close(e.writeChannel)
			return
		}
	}
}

func writeLines(e *EchoClient) {
	for line := range e.writeChannel {
		_, err := e.writer.WriteString(line)
		if err != nil {
			log.Print("writeLines:", err)
			break
		}
		e.writer.Flush()
	}
	e.closeChannel <- true
	e.conn.Close()
}

func runServer() error {
	ln, err := net.Listen("tcp", ":4040")
	if err != nil {
		return err
	}
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Print("Accept:", err)
		}
		e := NewEchoClient(conn)
		go readLines(e)
		go writeLines(e)
	}
}

func main() {
	err := runServer()
	if err != nil {
		log.Fatal("runServer:", err);
	}
}<commit_msg>Implemented a basic chat server<commit_after>package main

import (
	"bufio"
	"log"
	"net"
	)

var addChannel = make(chan *ChatClient)
var removeChannel = make(chan *ChatClient)
var chatChannel = make(chan string)

type ChatClient struct {
	conn net.Conn
	reader *bufio.Reader
	writer *bufio.Writer
	writeChannel chan string
	closeChannel chan bool
}

func NewChatClient(conn net.Conn) (c *ChatClient) {
	c = new(ChatClient)
	c.conn = conn
	c.reader = bufio.NewReader(conn)
	c.writer = bufio.NewWriter(conn)
	c.writeChannel = make(chan string)
	c.closeChannel = make(chan bool)
	return
}

func readLines(c *ChatClient) {
	for {
		line, err := c.reader.ReadString('\n')
		if err != nil {
			log.Print("readLines:", err)
			close(c.writeChannel)
			<-c.closeChannel // Let the write goroutine exit. Could use a buffered close channel instead?
			return
		}
		select {
		case chatChannel <- line:
			continue
		case <-c.closeChannel: // If a write error occurred.
			close(c.writeChannel)
			return
		}
	}
}

func writeLines(c *ChatClient) {
	for line := range c.writeChannel {
		_, err := c.writer.WriteString(line)
		if err != nil {
			log.Print("writeLines:", err)
			break
		}
		c.writer.Flush()
	}
	c.closeChannel <- true
	removeChannel <- c
	c.conn.Close()
}

func processChatCommands() {
	clients := make([]*ChatClient, 0)
	for {
		select {
		case client := <-addChannel:
			clients = append(clients, client)
		case client := <-removeChannel:
			found := -1
			for i, v := range clients {
				if v == client {
					found = i
					break
				}
			}
			if found >= 0 {
				clients = append(clients[:found], clients[found+1:]...)
			}
		case line := <-chatChannel:
			for i := 0; i < len(clients); i++ {
				clients[i].writeChannel <- line
			}
		}		
	}
}

func runServer() error {
	ln, err := net.Listen("tcp", ":4040")
	if err != nil {
		return err
	}
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Print("Accept:", err)
		}
		c := NewChatClient(conn)
		go readLines(c)
		go writeLines(c)
		addChannel <- c
	}
}

func main() {
	go processChatCommands()
	err := runServer()
	if err != nil {
		log.Fatal("runServer:", err);
	}
}
{'fraction_non_alphanumeric': 0.14620052008090148, 'fraction_numerical': 0.0037561398439757295, 'mean_word_length': 3.1660649819494586, 'pattern_counts': {'":': 2, '<': 17, '<?xml version=': 0, '>': 4, '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': '6279401', 'n_tokens_mistral': 1435, 'n_tokens_neox': 1287, 'n_words': 324}