func (l *LoginAttempt) UnmarshalText(text []byte) error {
	str := string(text)
	idx := 0  
	switch str[idx] {
	case ' ':
		idx++
		l.Success = true
		l.UserID = str[idx : idx+UserIDLength]
		idx += UserIDLength
	case '-':
		idx++
		l.Success = false
		l.UserID = str[idx : idx+UserIDLength]
		idx += UserIDLength
	case '[':
		l.Success = false
		l.UserID = ""
	default:
		return ErrInvalidLoginsBadFormat
	}
	l.UserID = strings.TrimSpace(l.UserID)
	t, err := time.Parse(loginStartTimeFormatString, str[idx:idx+len(loginStartTimeFormatString)])
	if err != nil {
		return err
	}
	l.LoginStartTime = t
	idx += len(loginStartTimeFormatString)
	l.FromHost = strings.TrimLeft(str[idx+1:], fromHostPrefix)
	return nil
}
UnmarshalText implements encoding.TextUnmarshaler to unmarshal text to the receiver
package pttbbs
import (
	"bufio"
	"errors"
	"fmt"
	"log"
	"os"
	"strings"
	"time"
)
const (
	UserIDLength = 12
	fromHostPrefix             = "?@"
	loginStartTimeFormatString = "[01/02/2006 15:04:05 Mon]"
)
var (
	ErrInvalidLoginsBadFormat = errors.New("Invalid logins.bad line format")
)
type LoginAttempt struct {
	Success        bool
	UserID         string
	LoginStartTime time.Time
	FromHost       string
}
func OpenBadLoginFile(filename string) ([]*LoginAttempt, error) {
	file, err := os.Open(filename)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	var ret []*LoginAttempt
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Bytes()
		a := &LoginAttempt{}
		err = a.UnmarshalText(line)
		if err != nil {
			return nil, err
		}
		ret = append(ret, a)
	}
	return ret, nil
}