database (#4)
Co-authored-by: Evan Burkey <dev@fputs.com> Reviewed-on: https://git.fputs.com/fputs/protohackers/pulls/4
This commit is contained in:
parent
3bd3a895b5
commit
0499ea30fe
|
@ -0,0 +1,55 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"protohackers/pkg/conn"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
l, err := net.Listen(conn.Type, conn.Port)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
|
||||||
|
fmt.Println(fmt.Sprintf("Listening on port %s", conn.Port))
|
||||||
|
|
||||||
|
r := createRoom()
|
||||||
|
for {
|
||||||
|
c, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
go handleConn(r, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleConn(r *room, c net.Conn) {
|
||||||
|
u := newUser(c)
|
||||||
|
defer c.Close()
|
||||||
|
go u.sendMessage()
|
||||||
|
|
||||||
|
u.write("Welcome to budgetchat! What shall I call you?")
|
||||||
|
|
||||||
|
s := bufio.NewScanner(u.conn)
|
||||||
|
for s.Scan() {
|
||||||
|
input := s.Text()
|
||||||
|
if !u.online {
|
||||||
|
r.sendToRest(r.joinMsg(u), u)
|
||||||
|
u.write(r.connectMsg())
|
||||||
|
r.joinUser(u)
|
||||||
|
} else {
|
||||||
|
r.sendToRest(msgWrap(input, u), u)
|
||||||
|
}
|
||||||
|
if s.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func msgWrap(msg string, u *user) string {
|
||||||
|
return fmt.Sprintf("[%s] %s", u.nick, msg)
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type room struct {
|
||||||
|
users []*user
|
||||||
|
}
|
||||||
|
|
||||||
|
func createRoom() *room {
|
||||||
|
return &room{
|
||||||
|
users: make([]*user, 16),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *room) joinUser(u *user) {
|
||||||
|
for _, usr := range r.users {
|
||||||
|
if usr.nick == u.nick {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.users = append(r.users, u)
|
||||||
|
u.online = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *room) sendToAll(msg string) {
|
||||||
|
for _, u := range r.users {
|
||||||
|
if u.online {
|
||||||
|
u.write(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *room) sendToRest(msg string, skip *user) {
|
||||||
|
for _, u := range r.users {
|
||||||
|
if u.online && u != skip {
|
||||||
|
u.write(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *room) connected() (nicks []string) {
|
||||||
|
for _, u := range r.users {
|
||||||
|
if u.online {
|
||||||
|
nicks = append(nicks, u.nick)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nicks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *room) joinMsg(u *user) string {
|
||||||
|
return fmt.Sprintf("* %s has joined the channel", u.nick)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *room) connectMsg() string {
|
||||||
|
return fmt.Sprintf("* The room contains: %s", strings.Join(r.connected(), ", "))
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type user struct {
|
||||||
|
conn net.Conn
|
||||||
|
nick string
|
||||||
|
online bool
|
||||||
|
output chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUser(conn net.Conn) *user {
|
||||||
|
return &user{
|
||||||
|
conn: conn,
|
||||||
|
output: make(chan string),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *user) write(s string) {
|
||||||
|
u.output <- s + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *user) sendMessage() {
|
||||||
|
for line := range u.output {
|
||||||
|
u.conn.Write([]byte(line))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"protohackers/pkg/conn"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
db map[string]string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
db = make(map[string]string)
|
||||||
|
db["version"] = "0.1.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := conn.StartSimpleUDP(handler, 1024)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handler(c *net.UDPConn, addr *net.UDPAddr, data []byte) {
|
||||||
|
if strings.Contains(string(data), "version=") {
|
||||||
|
return
|
||||||
|
} else if strings.Contains(string(data), "=") {
|
||||||
|
sp := strings.SplitN(string(data), "=", 2)
|
||||||
|
db[sp[0]] = sp[1]
|
||||||
|
} else {
|
||||||
|
out := fmt.Sprintf("%s=", string(data))
|
||||||
|
if v, ok := db[string(data)]; ok {
|
||||||
|
out += v
|
||||||
|
}
|
||||||
|
c.WriteTo([]byte(out), addr)
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,17 +8,16 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Port = ":3030"
|
Port = ":3030"
|
||||||
Type = "tcp4"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func StartSimple(handler func(conn net.Conn)) error {
|
func StartSimple(handler func(conn net.Conn)) error {
|
||||||
l, err := net.Listen(Type, Port)
|
l, err := net.Listen("tcp4", Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
fmt.Println(fmt.Sprintf("Listening on port %s", Port))
|
fmt.Println(fmt.Sprintf("Listening TCP on port %s", Port))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
c, err := l.Accept()
|
c, err := l.Accept()
|
||||||
|
@ -26,9 +25,30 @@ func StartSimple(handler func(conn net.Conn)) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go handler(c)
|
go handler(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartSimpleUDP(handler func(*net.UDPConn, *net.UDPAddr, []byte), buffSize int) error {
|
||||||
|
srv, err := net.ResolveUDPAddr("udp4", Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c, err := net.ListenUDP("udp4", srv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
fmt.Println(fmt.Sprintf("Listening UDP on port %s", Port))
|
||||||
|
|
||||||
|
buf := make([]byte, buffSize)
|
||||||
|
for {
|
||||||
|
n, addr, err := c.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go handler(c, addr, buf[:n])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue