<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/gophergala2016/3wordgame/validation"
	"net"
)

// Client struct
type Client struct {
	incoming chan Message
	outgoing chan string
	reader *bufio.Reader
	writer *bufio.Writer
	address string
}

type Message struct {
	text string
	address string
}

// Read line by line into the client.incoming
func (client *Client) Read() {
	for {
		line, _ := client.reader.ReadString('\n')
		client.incoming <- Message{
				text: line,
				address: client.address,
			}
	}
}

// Write client outgoing data to the client writer
func (client *Client) Write() {
	for data := range client.outgoing {
		client.writer.WriteString(data)
		client.writer.Flush()
	}
}

// Listen for reads and writes on the client
func (client *Client) Listen() {
	go client.Read()
	go client.Write()
}

// NewClient returns new instance of client.
func NewClient(connection net.Conn) *Client {
	writer := bufio.NewWriter(connection)
	reader := bufio.NewReader(connection)

	address := connection.RemoteAddr().String()

	client := &Client{
		incoming: make(chan Message),
		outgoing: make(chan string),
		reader:   reader,
		writer:   writer,
		address: address,
	}

	client.Listen()

	return client
}

// ChatRoom struct
type ChatRoom struct {
	clients  []*Client
	joins    chan net.Conn
	incoming chan Message
	outgoing chan string
	story string
	last_msg_user_address string
}

// Broadcast data to all connected chatRoom.clients
func (chatRoom *ChatRoom) Broadcast(data string) {
	for _, client := range chatRoom.clients {
		client.outgoing <- data
	}
}

// Join attaches a new client to the chatRoom clients
func (chatRoom *ChatRoom) Join(connection net.Conn) {
	client := NewClient(connection)
	chatRoom.clients = append(chatRoom.clients, client)
	go func() {
		for {
			chatRoom.incoming <- <-client.incoming
		}
	}()
}

// Listen to all incoming messages for the chatRoom
func (chatRoom *ChatRoom) Listen() {
	go func() {
		for {
			select {
			case data := <-chatRoom.incoming:
				msg, err := validation.ValidateMsg(data.text)
				if err == nil && chatRoom.last_msg_user_address != data.address {
					chatRoom.Broadcast(msg)
					chatRoom.story = fmt.Sprintf("%s %s", chatRoom.story, msg)
					chatRoom.last_msg_user_address = data.address
				}
			case conn := <-chatRoom.joins:
				chatRoom.Join(conn)
			}
		}
	}()
}

// NewChatRoom factories a ChatRoom instance
func NewChatRoom() *ChatRoom {
	chatRoom := &ChatRoom{
		clients:  make([]*Client, 0),
		joins:    make(chan net.Conn),
		incoming: make(chan Message),
		outgoing: make(chan string),
	}

	chatRoom.Listen()
<commit_msg>Send story when joining ChatRoom<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/gophergala2016/3wordgame/validation"
	"net"
)

// Client struct
type Client struct {
	incoming chan Message
	outgoing chan string
	reader *bufio.Reader
	writer *bufio.Writer
	address string
}

type Message struct {
	text string
	address string
}

// Read line by line into the client.incoming
func (client *Client) Read() {
	for {
		line, _ := client.reader.ReadString('\n')
		client.incoming <- Message{
				text: line,
				address: client.address,
			}
	}
}

// Write client outgoing data to the client writer
func (client *Client) Write() {
	for data := range client.outgoing {
		client.writer.WriteString(data)
		client.writer.Flush()
	}
}

// Listen for reads and writes on the client
func (client *Client) Listen() {
	go client.Read()
	go client.Write()
}

// NewClient returns new instance of client.
func NewClient(connection net.Conn) *Client {
	writer := bufio.NewWriter(connection)
	reader := bufio.NewReader(connection)

	address := connection.RemoteAddr().String()

	client := &Client{
		incoming: make(chan Message),
		outgoing: make(chan string),
		reader:   reader,
		writer:   writer,
		address: address,
	}

	client.Listen()

	return client
}

// ChatRoom struct
type ChatRoom struct {
	clients  []*Client
	joins    chan net.Conn
	incoming chan Message
	outgoing chan string
	story string
	last_msg_user_address string
}

// Broadcast data to all connected chatRoom.clients
func (chatRoom *ChatRoom) Broadcast(data string) {
	for _, client := range chatRoom.clients {
		client.outgoing <- data
	}
}

// Join attaches a new client to the chatRoom clients
func (chatRoom *ChatRoom) Join(connection net.Conn) {
	client := NewClient(connection)
	chatRoom.clients = append(chatRoom.clients, client)
	client.outgoing <- chatRoom.story
	go func() {
		for {
			chatRoom.incoming <- <-client.incoming
		}
	}()
}

// Listen to all incoming messages for the chatRoom
func (chatRoom *ChatRoom) Listen() {
	go func() {
		for {
			select {
			case data := <-chatRoom.incoming:
				msg, err := validation.ValidateMsg(data.text)
				if err == nil && chatRoom.last_msg_user_address != data.address {
					chatRoom.Broadcast(msg)
					if len(chatRoom.story) == 0 {
						chatRoom.story = msg
					} else {
						chatRoom.story = fmt.Sprintf("%s %s", chatRoom.story, msg)
					}
					chatRoom.last_msg_user_address = data.address
				}
			case conn := <-chatRoom.joins:
				chatRoom.Join(conn)
			}
		}
	}()
}

// NewChatRoom factories a ChatRoom instance
func NewChatRoom() *ChatRoom {
	chatRoom := &ChatRoom{
		clients:  make([]*Client, 0),
		joins:    make(chan net.Conn),
		incoming: make(chan Message),
		outgoing: make(chan string),
	}

	chatRoom.Listen()

{'fraction_non_alphanumeric': 0.11842105263157894, 'fraction_numerical': 0.0024091919940696814, 'mean_word_length': 3.6286449399656946, 'pattern_counts': {'":': 0, '<': 16, '<?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': '5239609', 'n_tokens_mistral': 1960, 'n_tokens_neox': 1779, 'n_words': 496}