<commit_before>package multi

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	"github.com/zenazn/goji/web"
	"golang.org/x/image/font"
	"golang.org/x/image/math/fixed"
	"image"
	"image/color"
	"image/draw"
	"net/http"
	"net/url"
	"github.com/cubeee/go-sig/signature/generators"
	"github.com/cubeee/go-sig/signature/util"
	"strconv"
	"github.com/cubeee/go-sig/signature"
)

var (
	baseWidth     = 400
	baseHeight    = 25
	bottomPadding = 20
	paddingSides  = 5
	dpi           = 72.0
	baseFont      = util.LoadFont("./resources/assets/fonts/MuseoSans_500.ttf")
	fontColor     = image.NewUniform(color.RGBA{245, 178, 65, 255})
	size          = 15.0
)

type MultiGoalGenerator struct {
	generators.Generator
}

type MultiGoal struct {
	skill    util.Skill
	goal     int
	goalType util.GoalType
}

func (m MultiGoalGenerator) CreateSignature(req util.ParsedSignatureRequest) (util.Signature, error) {
	username := req.GetProperty("username").(string)
	goals := req.GetProperty("goals").([]MultiGoal)

	stats, err := util.GetStats(username)
	if err != nil {
		var s util.Signature
		return s, errors.New(fmt.Sprintf("Failed to fetch stats for %s", username))
	}

	c := freetype.NewContext()

	createDrawer := func(img draw.Image, color *image.Uniform, f *truetype.Font,
		size float64, dpi float64, hinting font.Hinting) *font.Drawer {
		return &font.Drawer{
			Dst: img,
			Src: color,
			Face: truetype.NewFace(f, &truetype.Options{
				Size:    size,
				DPI:     dpi,
				Hinting: hinting,
			})}
	}

	baseImage := loadBaseImage(len(goals))

	drawer := createDrawer(baseImage, fontColor, baseFont, size, dpi, font.HintingFull)

	drawString := func(str string, x fixed.Int26_6, y int) {
		drawer.Dot = fixed.Point26_6{
			X: x,
			Y: fixed.I(y + int(c.PointToFixed(size)>>6)),
		}
		drawer.DrawString(str)
	}

	drawRightAlignedString := func(str string, x, y int) {
		width := drawer.MeasureString(str)
		drawString(str, fixed.I(x)-width, y)
	}

	nameX, goalX := paddingSides, baseWidth-paddingSides
	y := paddingSides

	for _, goal := range goals {
		stat := util.GetStatBySkill(stats, goal.skill)

		currentLevel := util.LevelFromXP(stat.Skill, stat.Xp)
		currentXP := stat.Xp
		var goalXP int
		var remainder int
		if goal.goalType == util.GoalXP {
			goalXP = goal.goal
			remainder = goalXP - currentXP
		} else {
			goalXP = util.XPForLevel(stat.Skill, goal.goal)
			remainder = util.XPToLevel(stat.Skill, currentXP, goal.goal)
		}
		goalLevel := util.LevelFromXP(stat.Skill, goalXP)
		if remainder < 0 {
			remainder = 0
		}
		percent := int(float64(currentXP) / float64(goalXP) * 100.0)
		if percent > 100 {
			percent = 100
		}

		// Skill name and current level
		drawString(
			fmt.Sprintf("%s: %d/%d", goal.skill.Name, currentLevel, goalLevel),
			fixed.I(nameX), y)

		// Current and goal xp
		drawRightAlignedString(util.Format(currentXP)+"/"+util.Format(goalXP), goalX, y)

		// Bar
		drawBar(baseImage, percent, nameX, y+20, baseWidth-5, 1)

		y += baseHeight
	}

	// Watermark
	y -= 5
	drawer = createDrawer(baseImage, fontColor, baseFont, 11, dpi, font.HintingFull)
	drawRightAlignedString(vars.VirtualHost, goalX, y)

	return util.Signature{Username: username, Image: baseImage}, nil
}

func (m MultiGoalGenerator) Name() string {
	return "multi"
}
<commit_msg>Fix bar length in multiple goal signatures<commit_after>package multi

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	"github.com/zenazn/goji/web"
	"golang.org/x/image/font"
	"golang.org/x/image/math/fixed"
	"image"
	"image/color"
	"image/draw"
	"net/http"
	"net/url"
	"github.com/cubeee/go-sig/signature/generators"
	"github.com/cubeee/go-sig/signature/util"
	"strconv"
	"github.com/cubeee/go-sig/signature"
)

var (
	baseWidth     = 400
	baseHeight    = 25
	bottomPadding = 20
	paddingSides  = 5
	dpi           = 72.0
	baseFont      = util.LoadFont("./resources/assets/fonts/MuseoSans_500.ttf")
	fontColor     = image.NewUniform(color.RGBA{245, 178, 65, 255})
	size          = 15.0
)

type MultiGoalGenerator struct {
	generators.Generator
}

type MultiGoal struct {
	skill    util.Skill
	goal     int
	goalType util.GoalType
}

func (m MultiGoalGenerator) CreateSignature(req util.ParsedSignatureRequest) (util.Signature, error) {
	username := req.GetProperty("username").(string)
	goals := req.GetProperty("goals").([]MultiGoal)

	stats, err := util.GetStats(username)
	if err != nil {
		var s util.Signature
		return s, errors.New(fmt.Sprintf("Failed to fetch stats for %s", username))
	}

	c := freetype.NewContext()

	createDrawer := func(img draw.Image, color *image.Uniform, f *truetype.Font,
		size float64, dpi float64, hinting font.Hinting) *font.Drawer {
		return &font.Drawer{
			Dst: img,
			Src: color,
			Face: truetype.NewFace(f, &truetype.Options{
				Size:    size,
				DPI:     dpi,
				Hinting: hinting,
			})}
	}

	baseImage := loadBaseImage(len(goals))

	drawer := createDrawer(baseImage, fontColor, baseFont, size, dpi, font.HintingFull)

	drawString := func(str string, x fixed.Int26_6, y int) {
		drawer.Dot = fixed.Point26_6{
			X: x,
			Y: fixed.I(y + int(c.PointToFixed(size)>>6)),
		}
		drawer.DrawString(str)
	}

	drawRightAlignedString := func(str string, x, y int) {
		width := drawer.MeasureString(str)
		drawString(str, fixed.I(x)-width, y)
	}

	nameX, goalX := paddingSides, baseWidth-paddingSides
	y := paddingSides

	for _, goal := range goals {
		stat := util.GetStatBySkill(stats, goal.skill)

		currentLevel := util.LevelFromXP(stat.Skill, stat.Xp)
		currentXP := stat.Xp
		var goalXP int
		var remainder int
		if goal.goalType == util.GoalXP {
			goalXP = goal.goal
			remainder = goalXP - currentXP
		} else {
			goalXP = util.XPForLevel(stat.Skill, goal.goal)
			remainder = util.XPToLevel(stat.Skill, currentXP, goal.goal)
		}
		goalLevel := util.LevelFromXP(stat.Skill, goalXP)
		if remainder < 0 {
			remainder = 0
		}
		percent := int(float64(currentXP) / float64(goalXP) * 100.0)
		if percent > 100 {
			percent = 100
		}

		// Skill name and current level
		drawString(
			fmt.Sprintf("%s: %d/%d", goal.skill.Name, currentLevel, goalLevel),
			fixed.I(nameX), y)

		// Current and goal xp
		drawRightAlignedString(util.Format(currentXP)+"/"+util.Format(goalXP), goalX, y)

		// Bar
		drawBar(baseImage, percent, nameX, y+20, baseWidth-5-paddingSides, 1)

		y += baseHeight
	}

	// Watermark
	y -= 5
	drawer = createDrawer(baseImage, fontColor, baseFont, 11, dpi, font.HintingFull)
	drawRightAlignedString(vars.VirtualHost, goalX, y)

	return util.Signature{Username: username, Image: baseImage}, nil
}

func (m MultiGoalGenerator) Name() string {
	return "multi"
}

{'fraction_non_alphanumeric': 0.13733969579481062, 'fraction_numerical': 0.018490903668356696, 'mean_word_length': 3.723239436619718, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, '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': '6635354', 'n_tokens_mistral': 2862, 'n_tokens_neox': 2526, 'n_words': 526}