text:
// Copyright © 2018 MG <mailtomasterg@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package game

import (
	"github.com/golang/protobuf/proto"
	"github.com/master-g/gouno/api/pb"
	"github.com/master-g/gouno/internal/uno"
)

var actionReqHandler = &FrameHandler{
	ReqCmd:  pb.GameCmd_ACTION_REQ,
	RespCmd: pb.GameCmd_ACTION_RESP,
	Handler: func(c *Client, t *Table, frame pb.Frame) (result HandleResult) {
		result.Status = int32(pb.StatusCode_STATUS_OK)
		body := &pb.S2CActionResp{
			Result: int32(pb.ActionResult_ACTION_RESULT_OK),
		}
		if t.Stage != StagePlaying {
			result.Status = int32(pb.StatusCode_STATUS_INVALID)
			body.Result = int32(pb.ActionResult_ACTION_RESULT_GAME_NOT_START)
			result.Msg = "game not started"
			return
		}
		if t.CurrentPlayer != c.UID {
			result.Status = int32(pb.StatusCode_STATUS_INVALID)
			body.Result = int32(pb.ActionResult_ACTION_RESULT_NOT_TURN)
			result.Msg = "not your turn"
			return
		}
		state, ok := t.stateMap[c.UID]
		if !ok {
			result.Status = int32(pb.StatusCode_STATUS_INTERNAL_ERROR)
			body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
			result.Msg = "player state not exists"
			return
		}

		req := pb.C2SActionReq{}
		result.Err = proto.Unmarshal(frame.Body, &req)
		if result.Err != nil {
			result.Status = int32(pb.StatusCode_STATUS_INVALID)
			body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
			result.Msg = result.Err.Error()
			return
		}

		switch req.Action {
		case int32(pb.Action_ACTION_PLAY):
			fallthrough
		case int32(pb.Action_ACTION_UNO_PLAY):
			handlePlay(t, req, state, body, &result)
		case int32(pb.Action_ACTION_DRAW):
			handleDraw(t, req, state, body, &result)
		case int32(pb.Action_ACTION_KEEP):
			handleKeep(t, req, state, body, &result)
		case int32(pb.Action_ACTION_CHALLENGE):
			handleChallenge(t, req, state, body, &result)
		case int32(pb.Action_ACTION_ACCEPT):
			handleAccept(t, req, state, body, &result)
		default:
			result.Status = int32(pb.StatusCode_STATUS_INVALID)
			result.Msg = "invalid action"
		}

		result.Body, result.Err = proto.Marshal(body)
		if result.Err != nil {
			result.Msg = result.Err.Error()
			result.Status = int32(pb.StatusCode_STATUS_INTERNAL_ERROR)
		}

		return
	},
}

func init() {
	addHandler(actionReqHandler)
}

func handlePlay(t *Table, action pb.C2SActionReq, state *PlayerState, body *pb.S2CActionResp, result *HandleResult) {
	result.Status = int32(pb.StatusCode_STATUS_OK)
	// if CHALLENGE flag is set, play can only choose to accept or challenge
	if state.IsFlagSet(int32(pb.PlayerStatus_STATUS_CHALLENGE)) {
		result.Msg = "you can only challenge or accept wild draw 4"
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		return
	}
	// must play one card
	if len(action.Card) != 1 {
		result.Msg = "only one card are allowed"
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		return
	}
	// must play his/her own card
	cardIndex := 0
	if cardIndex = state.CardIndex(action.Card[0]); cardIndex == -1 {
		result.Msg = "card does not exists"
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_CARD_NOT_EXIST)
		return
	}
	// wild card must have non wild color
	if !isColorValidForWildCard(action.Card[0], uint8(action.Color)) {
		result.Msg = "must specify color while play wild"
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_NEED_COLOR)
		return
	}

	if state.IsFlagSet(int32(pb.PlayerStatus_STATUS_DRAW)) {
		// player draw card from deck
		if cardIndex != len(state.Cards)-1 {
			// player must play or keep its last draw card after draw
			result.Msg = "you can only keep or play the card from your last draw"
			result.Status = int32(pb.StatusCode_STATUS_INVALID)
			body.Result = int32(pb.ActionResult_ACTION_RESULT_NOT_DRAW_CARD)
			return
		}
	}
	// else process as normal play

	//
	actionCard := action.Card[0]
	actionColor := uno.CardColor(actionCard)
	actionValue := uno.CardValue(actionCard)
	discardTop := t.Discard[len(t.Discard)-1]
	discardTopValue := uno.CardValue(discardTop)
	discardTopColor := uno.CardColor(discardTop)
	if actionColor == uno.ColorWild {
		actionColor = uint8(action.Color)
	}
	if discardTopColor == uno.ColorWild {
		discardTopColor = t.Color
	}

	if !t.DeckRecycled && len(t.Discard) == 1 && discardTopValue == uno.ValueWild {
		// the first card of the table is wild, player can play any card
	} else if actionValue == uno.ValueWild || actionValue == uno.ValueWildDraw4 {
		// player play wild or wild+4
	} else if discardTopValue == uno.ValueWild || discardTopValue == uno.ValueWildDraw4 {
		// last card in discard pile is wild/wild+4
		if actionColor != discardTopColor {
			// must match wild color
			result.Msg = "color mismatched"
			result.Status = int32(pb.StatusCode_STATUS_INVALID)
			body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
			return
		}
	} else if actionValue != discardTopValue && actionColor != discardTopColor {
		// one of the value/color must match the top of the discard pile
		result.Msg = "color or value must match with the last card played"
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		return
	}

	result.Events = make([]*pb.SingleEvent, 0)

	// card played
	body.Card = append(body.Card, actionCard)
	state.Cards = append(state.Cards[:cardIndex], state.Cards[cardIndex+1:]...)

	// clear player flag
	state.ClearFlag(int32(pb.PlayerStatus_STATUS_DRAW))

	t.LastPlayer = state.UID

	// events
	playEvent := &pb.SingleEvent{
		Uid:   state.UID,
		Event: int32(pb.Event_EVENT_PLAY),
		Card:  make([]byte, 1),
	}
	if action.Action == int32(pb.Action_ACTION_UNO_PLAY) {
		playEvent.Event = int32(pb.Event_EVENT_UNO_PLAY)
	}
	playEvent.Card[0] = actionCard
	result.Events = append(result.Events, playEvent)

	// action card effects
	var drawCount int
	skip := false

	switch actionValue {
	case uno.ValueReverse:
		t.Clockwise = !t.Clockwise
		result.Events = append(result.Events, &pb.SingleEvent{
			Event: int32(pb.Event_EVENT_REVERSE),
		})
		if len(t.States) == 2 {
			// when there are only two players, reverse has effect as skip
			skip = true
		}
	case uno.ValueDraw2:
		drawCount = uno.CardCount2
		skip = true
	case uno.ValueSkip:
		skip = true
		// case uno.ValueWildDraw4: if wild+4 is the last card of the player, should next player draw 4 cards before game over ?
	}

	// next player's turn
	nextPlayerUID := t.nextPlayer()

	if actionValue == uno.ValueWildDraw4 {
		// wild draw 4
		t.ChallengeColor = discardTopColor
		nextState := t.stateMap[nextPlayerUID]
		nextState.SetFlag(int32(pb.PlayerStatus_STATUS_CHALLENGE))
	}

	if drawCount > 0 {
		// draw cards
		drawCards(t, nextPlayerUID, drawCount, result)
	}

	if skip {
		// skip
		result.Events = append(result.Events, &pb.SingleEvent{
			Uid:   nextPlayerUID,
			Event: int32(pb.Event_EVENT_SKIP),
		})
		// to get next player's uid, need to set CurrentPlayer first
		t.CurrentPlayer = nextPlayerUID
		nextPlayerUID = t.nextPlayer()
	}

	// set next player
	t.CurrentPlayer = nextPlayerUID

	// check for uno
	if (len(state.Cards) == 1 && action.Action != int32(pb.Action_ACTION_UNO_PLAY)) || (len(state.Cards) > 1 && action.Action == int32(pb.Action_ACTION_UNO_PLAY)) {
		// penalty
		drawCards(t, state.UID, uno.CardCount2, result)
	}

	// there might be re-shuffle before, so put card in discard pile here
	t.Discard = append(t.Discard, actionCard)
	t.Color = actionColor

	// check for game over
	if len(state.Cards) == 0 {
		result.GameOver = true
	} else {
		result.Events = append(result.Events, &pb.SingleEvent{
			Uid:   nextPlayerUID,
			Event: int32(pb.Event_EVENT_TURN),
		})
	}

	// additional info for PLAY
	playEvent.Color = int32(t.Color)
	playEvent.Clockwise = t.Clockwise

	// reset timeout
	state.Timeout = false
	t.TimeLeft = t.Timeout
}

func handleDraw(t *Table, action pb.C2SActionReq, state *PlayerState, body *pb.S2CActionResp, result *HandleResult) {
	result.Events = make([]*pb.SingleEvent, 0)
	state.SetFlag(int32(pb.PlayerStatus_STATUS_DRAW))
	card := drawCards(t, state.UID, 1, result)
	body.Card = make([]uint8, 1)
	body.Card[0] = card[0]

	// reset timeout
	state.Timeout = false
	t.TimeLeft = t.Timeout
}

func handleKeep(t *Table, action pb.C2SActionReq, state *PlayerState, body *pb.S2CActionResp, result *HandleResult) {
	result.Status = int32(pb.StatusCode_STATUS_OK)
	if !state.IsFlagSet(int32(pb.PlayerStatus_STATUS_DRAW)) {
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		result.Msg = "you can only keep after drawing"
		return
	}

	result.Events = make([]*pb.SingleEvent, 0)
	state.ClearFlag(int32(pb.PlayerStatus_STATUS_DRAW))
	result.Events = append(result.Events, &pb.SingleEvent{
		Event: int32(pb.Event_EVENT_KEEP),
	})

	t.CurrentPlayer = t.nextPlayer()

	result.Events = append(result.Events, &pb.SingleEvent{
		Uid:   t.CurrentPlayer,
		Event: int32(pb.Event_EVENT_TURN),
	})

	state.Timeout = false
	t.TimeLeft = t.Timeout
}

func handleChallenge(t *Table, action pb.C2SActionReq, state *PlayerState, body *pb.S2CActionResp, result *HandleResult) {
	result.Status = int32(pb.StatusCode_STATUS_OK)
	if !state.IsFlagSet(int32(pb.PlayerStatus_STATUS_CHALLENGE)) {
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		result.Msg = "you can only challenge after a wild draw 4"
		return
	}
	// double check
	if len(t.Discard) < 2 || uno.CardValue(t.Discard[len(t.Discard)-1]) != uno.ValueWildDraw4 {
		result.Status = int32(pb.StatusCode_STATUS_INTERNAL_ERROR)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		result.Msg = "oops, something went wrong"
		return
	}

	// wild+4 will not trigger re-shuffle immediately
	prevCard := t.Discard[len(t.Discard)-2]
	// find if there are any available card
	lastPlayer, ok := t.stateMap[t.LastPlayer]
	if !ok {
		result.Status = int32(pb.StatusCode_STATUS_INTERNAL_ERROR)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		result.Msg = "oops, something went wrong, check LastPlayer logic"
		return
	}
	penalty := false
	for _, c := range lastPlayer.Cards {
		cardValue := uno.CardValue(c)
		cardColor := uno.CardColor(c)
		if cardValue == uno.ValueWild || cardColor == t.ChallengeColor || cardValue == uno.CardValue(prevCard) {
			penalty = true
			break
		}
	}

	result.Events = make([]*pb.SingleEvent, 0)
	state.ClearFlag(int32(pb.PlayerStatus_STATUS_CHALLENGE))

	if penalty {
		// challenge success
		// last player draw 4 cards, and wild + 4 remains in discard pile
		drawCards(t, lastPlayer.UID, uno.CardCount4, result)
	} else {
		// challenge failed
		// this player draw 6 cards, and miss his turn
		drawCards(t, state.UID, uno.CardCount6, result)
		t.CurrentPlayer = t.nextPlayer()
	}

	result.Events = append(result.Events, &pb.SingleEvent{
		Uid:   t.CurrentPlayer,
		Event: int32(pb.Event_EVENT_TURN),
	})

	// reset timeout
	state.Timeout = false
	t.TimeLeft = t.Timeout
}

func handleAccept(t *Table, action pb.C2SActionReq, state *PlayerState, body *pb.S2CActionResp, result *HandleResult) {
	result.Status = int32(pb.StatusCode_STATUS_OK)
	if !state.IsFlagSet(int32(pb.PlayerStatus_STATUS_CHALLENGE)) {
		result.Status = int32(pb.StatusCode_STATUS_INVALID)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		result.Msg = "you can only challenge after a wild draw 4"
		return
	}
	// double check
	if len(t.Discard) < 2 || uno.CardValue(t.Discard[len(t.Discard)-1]) != uno.ValueWildDraw4 {
		result.Status = int32(pb.StatusCode_STATUS_INTERNAL_ERROR)
		body.Result = int32(pb.ActionResult_ACTION_RESULT_INVALID)
		result.Msg = "oops, something went wrong"
		return
	}

	drawCards(t, state.UID, uno.CardCount4, result)
	t.CurrentPlayer = t.nextPlayer()

	state.ClearFlag(int32(pb.PlayerStatus_STATUS_CHALLENGE))

	// reset timeout
	result.Events = append(result.Events, &pb.SingleEvent{
		Uid:   t.CurrentPlayer,
		Event: int32(pb.Event_EVENT_TURN),
	})

	state.Timeout = false
	t.TimeLeft = t.Timeout
}

func isColorValidForWildCard(card, color uint8) bool {
	if uno.CardValue(card) == uno.ValueWild || uno.CardValue(card) == uno.ValueWildDraw4 {
		if color != uno.ColorRed &&
			color != uno.ColorYellow &&
			color != uno.ColorBlue &&
			color != uno.ColorGreen {
			return false
		}
	}

	return true
}

// helper function
func drawCards(t *Table, uid uint64, num int, result *HandleResult) []uint8 {
	card, err := t.Deck.Deals(num)
	if err != nil {
		// re-shuffle if needed
		result.Events = append(result.Events, t.recycleDiscardPile())
		card, _ = t.Deck.Deals(num)
	}
	drawEvent := &pb.SingleEvent{
		Uid:   uid,
		Event: int32(pb.Event_EVENT_DRAW),
		Card:  make([]uint8, num),
	}
	copy(drawEvent.Card, card)

	state := t.stateMap[uid]
	state.Cards = append(state.Cards, card...)

	result.Events = append(result.Events, drawEvent)

	return card
}

repository: master-g/gouno

repo_name: master-g/gouno


text:
# Copyright 2015, alex at staticlibs.net
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required ( VERSION 2.8.12 )

# default to Debug
set ( CMAKE_BUILD_TYPE "Debug" CACHE STRING "Default build type" )

set ( CMAKE_SYSTEM_NAME Linux )
set ( CMAKE_C_COMPILER gcc )
set ( CMAKE_CXX_COMPILER g++ )

# CMAKE_C_FLAGS
set ( CMAKE_C_FLAGS_LIST
        -fPIC )
string ( REPLACE ";" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS_LIST}" )
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE INTERNAL "" )

# CMAKE_C_FLAGS_DEBUG
set ( CMAKE_C_FLAGS_DEBUG_LIST
        -g
        -O0 )
string ( REPLACE ";" " " CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_LIST}" )
set ( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE INTERNAL "" )

# CMAKE_C_FLAGS_RELEASE
set ( CMAKE_C_FLAGS_RELEASE_LIST
        -Os
        -DNDEBUG )
string ( REPLACE ";" " " CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_LIST}" )
set ( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE INTERNAL "" )

# STATICLIB_CXX_STANDARD
if ( NOT DEFINED STATICLIB_CXX_STANDARD )
    set ( STATICLIB_CXX_STANDARD c++11 CACHE INTERNAL "" )
endif ( )

# CMAKE_CXX_FLAGS
set ( CMAKE_CXX_FLAGS_LIST
        --std=${STATICLIB_CXX_STANDARD}
        -fPIC
        -Wall
        -Werror
        -Wextra
        -fno-strict-overflow
        -fno-strict-aliasing
        -fstack-protector-all )
string ( REPLACE ";" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_LIST}" )
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE INTERNAL "" )

# CMAKE_CXX_FLAGS_DEBUG
set ( CMAKE_CXX_FLAGS_DEBUG_LIST
        -g
        -O0 )
string ( REPLACE ";" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_LIST}" )
set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE INTERNAL "" )

# CMAKE_CXX_FLAGS_RELEASE
set ( CMAKE_CXX_FLAGS_RELEASE_LIST
        -Os
        -DNDEBUG )
string ( REPLACE ";" " " CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_LIST}" )
set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE INTERNAL "" )

# valgrind
if ( EXISTS "/usr/bin/valgrind" )
    set ( CMAKE_MEMORYCHECK_COMMAND "/usr/bin/valgrind" CACHE INTERNAL "" )
    set ( CMAKE_MEMORYCHECK_COMMAND_OPTIONS
            --leak-check=yes
            --show-reachable=yes
            --track-origins=yes
            --error-exitcode=42
            --track-fds=yes
            --suppressions=${STATICLIB_CMAKE}/resources/valgrind/openssl_malloc.supp
            CACHE INTERNAL "" )
endif ( )

repository: pollend/cmake

license_type: permissive

repo_name: pollend/cmake

branch_name: refs/heads/master

extension: cmake


text:
package greenery_test

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/woodensquares/greenery"
)

type exampleMinimalConfig struct {
	*greenery.BaseConfig
	Timeout *greenery.IntValue `greenery:"get|timeout|t,      minimal-app.timeout,   TIMEOUT"`
}

func exampleNewMinimalConfig() *exampleMinimalConfig {
	cfg := &exampleMinimalConfig{
		BaseConfig: greenery.NewBaseConfig("minimal", map[string]greenery.Handler{
			"get<": exampleMinimalGetter,
		}),
		Timeout: greenery.NewIntValue("Timeout", 0, 1000),
	}

	if err := cfg.Timeout.SetInt(400); err != nil {
		panic("Could not initialize the timeout to its default")
	}

	return cfg
}

var exampleMinimalDocs = map[string]*greenery.DocSet{
	"en": &greenery.DocSet{
		Short: "URL fetcher",
		Usage: map[string]*greenery.CmdHelp{
			"get": &greenery.CmdHelp{
				Use:   "[URI to fetch]",
				Short: "Retrieves the specified page",
			},
		},
		CmdLine: map[string]string{
			"Timeout": "the timeout to use for the fetch",
		},
	},
}

func exampleMinimalGetter(lcfg greenery.Config, args []string) error {
	cfg := lcfg.(*exampleMinimalConfig)

	if len(args) != 1 {
		return fmt.Errorf("Invalid number of command line arguments")
	}

	cfg.Debugf("fetching %s, timeout %d", args[0], cfg.Timeout.Value)
	fmt.Printf("Will fetch %s with timeout %d milliseconds\n\n", args[0], cfg.Timeout.Value)
	return nil
}

func exampleMinimalMain() {
	cfg := exampleNewMinimalConfig()
	defer cfg.Cleanup()

	if err := cfg.Execute(cfg, exampleMinimalDocs); err != nil {
		fmt.Fprintf(os.Stderr, "Error executing: %s\n", err)
		os.Exit(1)
	}
}

// Example_minimal shows a minimal application using the greery
// library. Invocations mimicking actual command-line usage setting the
// parameter value in different ways are provided for reference.
func Example_minimal() {
	fmt.Println("----------------------------------------------------------")

	// Execute with no arguments, will use the default timeout
	os.Args = []string{"minimal", "get", "http://127.0.0.1"}
	fmt.Println("Executing with the default timeout")
	exampleMinimalMain()

	// Execute with a commandline timeout argument
	os.Args = []string{"minimal", "get", "-t", "300", "http://127.0.0.1"}
	fmt.Println("Executing with a commandline timeout")
	exampleMinimalMain()

	// Create a configuration file with a timeout value
	cfgFile, err := ioutil.TempFile("", "minimal")
	if err != nil {
		fmt.Println("Cannot create a temporary file")
		os.Exit(1)
	}
	defer func() {
		_ = os.Remove(cfgFile.Name())
	}()

	if _, err = cfgFile.Write([]byte(`# Sample config file
[minimal-app]
timeout = 550
`)); err != nil {
		fmt.Println("Cannot write the config file")
		os.Exit(1)
	}
	if err := cfgFile.Close(); err != nil {
		fmt.Println("Cannot close the config file")
		os.Exit(1)
	}

	// Execute with the created configuration file
	os.Args = []string{"minimal", "get", "-c", cfgFile.Name(), "http://127.0.0.1"}
	fmt.Println("Executing with a configuration file")
	exampleMinimalMain()

	// Execute with an environment variable argument, together with the
	// configuration file, note the environment variable will have precedence
	if err := os.Setenv("MINIMAL_TIMEOUT", "200"); err != nil {
		fmt.Println("Cannot set an environment variable")
		os.Exit(1)
	}

	os.Args = []string{"minimal", "get", "-c", cfgFile.Name(), "http://127.0.0.1"}
	fmt.Println("Executing with a configuration and environment variable timeout")
	exampleMinimalMain()

	// Executing with commandline, config and environment timeout argument,
	// the commandline will take precedence
	os.Args = []string{"minimal", "get", "-c", cfgFile.Name(), "-t", "300", "http://127.0.0.1"}
	fmt.Println("Executing with a commandline, configuration and environment timeout")
	exampleMinimalMain()

	// Output: ----------------------------------------------------------
	// Executing with the default timeout
	// Will fetch http://127.0.0.1 with timeout 400 milliseconds
	//
	// Executing with a commandline timeout
	// Will fetch http://127.0.0.1 with timeout 300 milliseconds
	//
	// Executing with a configuration file
	// Will fetch http://127.0.0.1 with timeout 550 milliseconds
	//
	// Executing with a configuration and environment variable timeout
	// Will fetch http://127.0.0.1 with timeout 200 milliseconds
	//
	// Executing with a commandline, configuration and environment timeout
	// Will fetch http://127.0.0.1 with timeout 300 milliseconds
	//
}

repository: woodensquares/greenery

repo_name: woodensquares/greenery

extension: go


text:
% Encoding: UTF-8

@Article{Hubbard2009,
  author       = {Hubbard, Mont},
  title        = {Safer ski jump landing surface design limits normal velocity at impact},
  volume       = {6},
  number       = {1},
  pages        = {175--183},
  abstract     = {Skiing and snowboarding have become more acrobatic with terrain park jumps and other
manmade features playing a prominent role in an increase in serious spinal cord injuries. Yet these jumps
rarely, if ever, involve formal or detailed design or engineering. This paper presents a coherent theory and
methodology for the design of ski jump landing surfaces. The motion of the skier center of mass is modeled.
Although jumpers may land in many configurations, we assume that the probability of severe landing injury
is correlated with the component of skier velocity perpendicular (normal) to the landing surface v or, more
understandably, with the corresponding equivalent fall height (EFH). The requirement that v and EFH be
small is satisfied by making the landing surface nearly parallel to the skier flight path at landing. Safer
landing surfaces that limit EFH to a given value are shown to satisfy a first order ordinary differential
equation (ODE). Having chosen an EFH deemed safe enough by the designer, integration of this ODE
provides members of an infinite family of landing surfaces that limit the EFH to the desired value, for any
jumper in-run velocity. Using the takeoff ramp angle as another design variable, one can choose a member
of this family to fit on almost any available jump site. The formulation incorporates the fact that skiers can
slightly modify velocity direction and magnitude at takeoff by jumping and is valid for any landing body
configuration. Such landing surfaces can still yield exhilarating flight experiences with relatively large flight
times and air height above the surface, but without the danger posed by jumps created in an ad hoc
manner, which can expose the skier to much larger unsafe equivalent fall heights.},
  date         = {2009},
  isbn         = {978-0-8031-3409-6},
  journaltitle = {Journal of ASTM International},
  language     = {en},
  doi          = {10.1520/STP47480S},
}

@MastersThesis{Swedberg2010,
  author      = {Andrew Davis Swedberg},
  title       = {Safer ski jumps: {D}esign of landing surfaces and clothoidal in-run transitions},
  date        = {2010},
  institution = {Naval Postgraduate School},
  urldate     = {2018-04-25},
  url = {http://www.dtic.mil/docs/citations/ADA524748},
}

@Article{McNeil2012,
  author       = {McNeil, James A. and Hubbard, Mont and Swedberg, Andrew D.},
  title        = {Designing tomorrow’s snow park jump},
  volume       = {15},
  number       = {1},
  pages        = {1--20},
  issn         = {1369-7072, 1460-2687},
  abstract     = {Recent epidemiological studies of injuries at ski resorts have found that snow park jumps pose a signiﬁcantly greater risk for certain classes of injury to resort patrons than other normal skiing activities. Today, most recreational jumps are built by skilled groomers without an engineering design process, but the Snow Skiing Committee (F-27) of the American Society for Testing and Materials is considering the inclusion of recreational jumps in their purview which may lead to a greater role for engineering jump designs in the US in the future. Similar efforts are underway in Europe as well. The purpose of this work is to review the current state of the science of snow park jumps, describe the jump design process, and outline the role that modelling will play in designing tomorrow’s snow park jumps.},
  date         = {2012-03},
  doi          = {10.1007/s12283-012-0083-x},
  journaltitle = {Sports Engineering},
  language     = {en},
  urldate      = {2018-03-25},
}

@Article{Levy2015,
  author       = {Levy, Dean and Hubbard, Mont and McNeil, James A. and Swedberg, Andrew},
  title        = {A design rationale for safer terrain park jumps that limit equivalent fall height},
  volume       = {18},
  number       = {4},
  pages        = {227--239},
  issn         = {1369-7072, 1460-2687},
  abstract     = {Ski jump landing surface shapes can be created to cushion jumper landing by specifying a value of equivalent fall height (EFH) but, because the shape is calculated by integrating a differential equation, an inﬁnite number of solutions results from the arbitrary boundary conditions. This paper provides a natural rationale for selection of the least expensive (minimum snow budget) one of these that nevertheless satisﬁes other design constraints, mainly limited normal acceleration and jerk during approach and landing transitions. Choosing the maximum allowable normal acceleration during the approach transition brings the entire inﬁnite family of landing surfaces as close as possible to the parent slope. Limiting the rate of change of normal acceleration (jerk) decreases the likelihood of loss of balance at takeoff and consequent catastrophic spinal cord injuries on landing. An analogous choice, satisfying limited normal acceleration during the landing transition, selects the single member of the inﬁnite family (providing the desired EFH) that lies closest to the parent slope and is therefore least costly to build. Software in the form of a graphical user interface is described that implements these algorithms and is appropriate for inexperienced users to calculate design details before actual fabrication of landing surfaces at a speciﬁc jump site.},
  date         = {2015-12},
  doi          = {10.1007/s12283-015-0182-6},
  journaltitle = {Sports Engineering},
  language     = {en},
  urldate      = {2018-03-25},
}

@Article{Petrone2017,
  author       = {Petrone, Nicola and Cognolato, Matteo and McNeil, James A. and Hubbard, Mont},
  title        = {Designing, building, measuring, and testing a constant equivalent fall height terrain park jump},
  volume       = {20},
  number       = {4},
  pages        = {283--292},
  issn         = {1369-7072, 1460-2687},
  abstract     = {Previous work has presented both a theoretical foundation for designing terrain park jumps that control landing impact and computer software to accomplish this task. US ski resorts have been reluctant to adopt this more engineered approach to jump design, in part due to questions of feasibility. The present study demonstrates this feasibility. It describes the design, construction, measurement, and experimental testing of such a jump. It improves on the previous efforts with more complete instrumentation, a larger range of jump distances, and a new method for combining jumper- and board-mounted accelerometer data to estimate equivalent fall height, a measure of impact severity. It unequivocally demonstrates the efﬁcacy of the engineering design approach, namely that it is possible and practical to design and build free style terrain park jumps with landing surface shapes that control for landing impact as predicted by the theory.},
  date         = {2017-12},
  doi          = {10.1007/s12283-017-0253-y},
  journaltitle = {Sports Engineering},
  language     = {en},
  urldate      = {2018-03-25},
}

@Misc{Jones2001,
  author = {Eric Jones and Travis Oliphant and Pearu Peterson and others},
  title  = {{SciPy}: Open source scientific tools for {Python}},
  date   = {2001--},
  url    = {http://www.scipy.org/},
}

@Article{Meurer2017,
  author       = {Meurer, Aaron and Smith, Christopher P. and Paprocki, Mateusz and Čertík, Ondřej and Kirpichev, Sergey B. and Rocklin, Matthew and Kumar, AMiT and Ivanov, Sergiu and Moore, Jason K. and Singh, Sartaj and Rathnayake, Thilina and Vig, Sean and Granger, Brian E. and Muller, Richard P. and Bonazzi, Francesco and Gupta, Harsh and Vats, Shivam and Johansson, Fredrik and Pedregosa, Fabian and Curry, Matthew J. and Terrel, Andy R. and Roučka, Štěpán and Saboo, Ashutosh and Fernando, Isuru and Kulal, Sumith and Cimrman, Robert and Scopatz, Anthony},
  title        = {{SymPy}: {s}ymbolic computing in {P}ython},
  volume       = {3},
  pages        = {e103},
  issn         = {2376-5992},
  abstract     = {SymPy is an open source computer algebra system written in pure Python. It is built with a focus on extensibility and ease of use, through both interactive and programmatic applications. These characteristics have led SymPy to become a popular symbolic library for the scientific Python ecosystem. This paper presents the architecture of SymPy, a description of its features, and a discussion of select submodules. The supplementary material provide additional examples and further outline details of the architecture and features of SymPy.},
  date         = {2017-01},
  doi          = {10.7717/peerj-cs.103},
  journaltitle = {PeerJ Computer Science},
  language     = {en},
  shorttitle   = {{SymPy}},
  url          = {https://peerj.com/articles/cs-103},
  urldate      = {2017-06-04},
}

@Article{Behnel2011,
  author       = {Behnel, S. and Bradshaw, R. and Citro, C. and Dalcin, L. and Seljebotn, D.S. and Smith, K.},
  title        = {Cython: {The} {Best} of {Both} {Worlds}},
  volume       = {13},
  number       = {2},
  pages        = {31--39},
  issn         = {1521-9615},
  date         = {2011-04},
  doi          = {10.1109/MCSE.2010.118},
  journaltitle = {Computing in Science Engineering},
  keywords     = {C language, Cython language, Fortran code, numerical analysis, numerical loops, programming language, Python language extension},
}

@Article{Hunter2007,
  author       = {John D. Hunter},
  title        = {Matplotlib: A 2D Graphics Environment},
  volume       = {9},
  pages        = {90--95},
  date         = {2007},
  doi          = {10.1109/MCSE.2007.55},
  journaltitle = {Computing in Science \& Engineering},
}

@Online{Plotly2015,
  author    = {{Plotly Technologies Inc.}},
  title     = {Plotly: {C}ollaborative data science},
  date      = {2015},
  location  = {Montreal, QC},
  publisher = {Plotly Technologies Inc.},
  url       = {https://plot.ly},
}

@Online{Brady2014,
  author = {P. Brady},
  title  = {{f}astcache},
  date   = {2014},
  url    = {https://github.com/pbrady/fastcache},
}

@Online{Pallets2018,
  author = {{Pallets Project}},
  title  = {Flask},
  date   = {2018},
  url    = {https://github.com/pallets/flask},
}

@Article{vanderWalt2011,
  author       = {Stéfan van der Walt and S. Chris Colbert and Gaël Varoquaux},
  title        = {The NumPy Array: A Structure for Efficient Numerical Computation},
  volume       = {13},
  number       = {2},
  pages        = {22--30},
  date         = {2011},
  doi          = {10.1109/MCSE.2011.37},
  eprint       = {https://aip.scitation.org/doi/pdf/10.1109/MCSE.2011.37},
  journaltitle = {Computing in Science \& Engineering},
}

@Article{Dahlgren2018,
  author       = {Björn Dahlgren},
  title        = {pyodesys: Straightforward numerical integration of ODE systems from Python},
  volume       = {3},
  pages        = {490},
  date         = {2018},
  doi          = {10.21105/joss.00490},
  issue        = {21},
  journaltitle = {Journal of Open Source Software},
}

@Comment{jabref-meta: databaseType:bibtex;}

repository: mechmotum/skijumpdesign

repo_name: mechmotum/skijumpdesign

extension: bib


text:
package main

import (
	"os"

	"github.com/jduhamel/sample"
)

func main() {
	err := sample.SendMessage("nats://localhost:6222")
	if err != nil {
		os.Exit(-1)
	}
}

license: MIT

repository: jduhamel/sample

repo_name: jduhamel/sample


text:
package main

import (
	"crypto"
	"flag"
	"fmt"
	"image/png"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	_ "crypto/md5"

	"github.com/mhcerri/abstracticon"
)

func main() {

	hashes := map[string]crypto.Hash{
		"md5": crypto.MD5,
	}

	var hashNames []string
	for n, _ := range hashes {
		hashNames = append(hashNames, n)
	}

	var (
		hashName    = flag.String("hash", "md5", "Hash function. Options: "+strings.Join(hashNames, ", "))
		multiplier  = flag.Int("multiplier", 8, "Number of pixels that represents a point.")
		points      = flag.Int("points", 8, "Number of points in the height and width of the image.")
		transparent = flag.Bool("transparent", false, "Use transparent background.")
		mirrored    = flag.Bool("mirrored", true, "Mirror the image left to right.")
		output      = flag.String("output", "output.png", "Output file.")
	)

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]\n", filepath.Base(os.Args[0]))
		fmt.Fprintf(os.Stderr, "Reads data from stdin and generates an icon. Options:\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	if *multiplier < 0 {
		log.Fatal("Invalid multiplier.")
	}
	if *points < 0 {
		log.Fatal("Invalid points.")
	}

	attrs := abstracticon.Attrs{
		Hash:        hashes[*hashName],
		Multiplier:  *multiplier,
		Points:      *points,
		Transparent: *transparent,
		NotMirrored: !*mirrored,
	}
	data, err := ioutil.ReadAll(os.Stdin)
	img := abstracticon.RenderFromBytes(data, attrs)
	file, err := os.Create(*output)
	if err != nil {
		log.Fatal(err)
	}
	err = png.Encode(file, img)
	if err != nil {
		log.Fatal(err)
	}
}

repository: mhcerri/abstracticon

repo_name: mhcerri/abstracticon


text:
package crypto

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"io/ioutil"
)

const blockType = "RSA PRIVATE KEY"

func DecodePrivateKeyFromFile(path string) (*rsa.PrivateKey, error) {

	// Read the file
	raw, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	// Decide the key
	key, err := DecodePrivateKey(raw)
	if err != nil {
		return nil, err
	}

	return key, nil
}

func DecodePrivateKey(raw []byte) (*rsa.PrivateKey, error) {

	// Decode
	block, _ := pem.Decode(raw)
	if block == nil || block.Type != blockType {
		return nil, errors.New("failed to decode PEM block containing RSA private key")
	}

	// TODO: Is this the right decode function?
	key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	return key, nil
}

func EncodePrivateKey(privateKey *rsa.PrivateKey) []byte {
	bytes := pem.EncodeToMemory(
		&pem.Block{
			Type:  blockType,
			Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
		},
	)

	return bytes
}

repository: YuKitsune/Orca

repo_name: YuKitsune/Orca

branch_name: refs/heads/main


text:
package commands

import (
	"time"

	"github.com/bwmarrin/discordgo"
)

func (c *GenericCommand) GetTimeZones(session *discordgo.Session, message *discordgo.MessageCreate) {
	//Locations
	newZealand, _ := time.LoadLocation("Pacific/Auckland")
	easternAustralia, _ := time.LoadLocation("Australia/Sydney")
	bulgaria, _ := time.LoadLocation("Europe/Sofia")
	generalEuropeTime, _ := time.LoadLocation("Europe/Prague")
	easternTime, _ := time.LoadLocation("America/Fort_Wayne")
	centralTime, _ := time.LoadLocation("America/Chicago")
	pacificTime, _ := time.LoadLocation("America/Los_Angeles")

	timeObject := time.Now()
	customString := "```py\n"
	customString += "NZST: " + timeObject.In(newZealand).Format("15:04:05") + " [Peaches]\n"
	customString += "AEST: " + timeObject.In(easternAustralia).Format("15:04:05") + " [FluffyXVI, CommonCrayon, JackT]\n"
	customString += "EEST: " + timeObject.In(bulgaria).Format("15:04:05") + " [KlixX]\n"
	customString += "CEST: " + timeObject.In(generalEuropeTime).Format("15:04:05") + " [Squinky, Slimek, Florian]\n"
	customString += "EST:  " + timeObject.In(easternTime).Format("15:04:05") + " [Squidski, Seth, Skratchpost, CSGO John Madden, Strangest Stranger, jamdoggie]\n"
	customString += "CST:  " + timeObject.In(centralTime).Format("15:04:05") + " [TopHATTwaffle, Kale, SUMOSUPREME]\n"
	customString += "PST:  " + timeObject.In(pacificTime).Format("15:04:05") + " [Ch(i)ef, Practical Problems]\n"
	customString += "```"
	session.ChannelMessageSend(message.ChannelID, customString)

}


text:
@article{SCHUG2023108997,
title = {High-resolution data and maps of material stock, population, and employment in Austria from 1985 to 2018},
journal = {Data in Brief},
pages = {108997},
year = {2023},
issn = {2352-3409},
doi = {https://doi.org/10.1016/j.dib.2023.108997},
url = {https://www.sciencedirect.com/science/article/pii/S2352340923001154},
author = {Franz Schug and Dominik Wiedenhofer and Helmut Haberl and David Frantz and Doris Virág and Sebastian {van der Linden} and Patrick Hostert},
keywords = {Buildings, Change aftereffect trend analysis, Industrial ecology, Infrastructure, Landsat, Socio-economic metabolism, Time series analysis},
abstract = {High-resolution maps of material stocks in buildings and infrastructures are of key importance for studies of societal resource use (social metabolism, circular economy, secondary resource potentials) as well as for transport studies and land system science. So far, such maps were only available for specific years but not in time series. Even for single years, data covering entire countries with high resolution, or using remote-sensing data are rare. Instead, they often have local extent (e.g., [1]), are lower resolution (e.g., [2]), or are based on other geospatial data (e.g., [3]). We here present data on the material stocks in three types of buildings (commercial and industrial, single- and multifamily houses) and three types of infrastructures (roads, railways, other infrastructures) for a 33-year time series for Austria at a spatial resolution of 30 m. The article also presents data on population and employment in Austria for the same time period, at the same spatial resolution. Data were derived with the same method applied in a recent study for Germany [4].}
}

repository: davidfrantz/academic-kickstart

repo_name: davidfrantz/academic-kickstart

gha_license_id: MIT


text:
SUMMARY = "Utilities for formatting and manipulating DocBook documents"
DESCRIPTION = "A collection of all the free software tools you need to \
work on and format DocBook documents."
HOMEPAGE = "http://sources.redhat.com/docbook-tools/"
SECTION = "console/utils"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f"
DEPENDS = "openjade-native sgmlspl-native docbook-dsssl-stylesheets-native docbook-sgml-dtd-3.1-native"

PR = "r2"

SRC_URI = "ftp://sources.redhat.com/pub/docbook-tools/new-trials/SOURCES/docbook-utils-${PV}.tar.gz"

SRC_URI[md5sum] = "6b41b18c365c01f225bc417cf632d81c"
SRC_URI[sha256sum] = "48faab8ee8a7605c9342fb7b906e0815e3cee84a489182af38e8f7c0df2e92e9"

inherit autotools native

do_configure_prepend() {
	# Fix hard-coded references to /etc/sgml
	if [ ! -e ${WORKDIR}/.sed_done ]; then
		sed -i -e "s|/etc/sgml|${sysconfdir}/sgml|g" bin/jw.in
		sed -i -e "s|/etc/sgml|${sysconfdir}/sgml|g" doc/man/Makefile.am
		sed -i -e "s|/etc/sgml|${sysconfdir}/sgml|g" doc/HTML/Makefile.am

		# Point jw to the native sysroot catalog
		sed -i -e 's|^SGML_EXTRA_CATALOGS=""|SGML_EXTRA_CATALOGS=":${sysconfdir}/sgml/catalog"|g' bin/jw.in
		touch ${WORKDIR}/.sed_done
	fi
}

do_install() {
	install -d ${D}${bindir}
	# Install the binaries and a bunch of other commonly used names for them.
	for doctype in html ps dvi man pdf rtf tex texi txt
	do
		install -m 0755 ${S}/bin/docbook2$doctype ${D}${bindir}/
		ln -sf docbook2x-$doctype ${D}${bindir}/db2$doctype
		ln -sf docbook2$doctype ${D}${bindir}/db2$doctype
		ln -sf docbook2$doctype ${D}${bindir}/docbook-to-$doctype
	done

	install -m 0755 ${S}/bin/jw ${D}${bindir}/
	for i in backends/dvi backends/html backends/man \
		backends/pdf backends/ps backends/rtf backends/tex \
		backends/texi backends/txt frontends/docbook \
		helpers/docbook2man-spec.pl helpers/docbook2texi-spec.pl \
		docbook-utils.dsl
	do
		install -d ${D}${datadir}/sgml/docbook/utils-${PV}/`dirname $i`
		install ${S}/$i ${D}${datadir}/sgml/docbook/utils-${PV}/$i
	done
}

extension: bb


text:
package envvars

import (
	"github.com/flemay/envvars/pkg/errorappender"
	"os"
)

// Ensure verifies that the environment variables comply to their Declaration. Tags can be passed along to only ensure environment variables with the tags
func Ensure(reader DeclarationReader, tags ...string) error {
	c, err := List(reader, tags...)
	if err != nil {
		return err
	}
	errorAppender := errorappender.NewErrorAppender("\n")
	for _, ev := range c {
		errorAppender.AppendError(ensureEnvvar(ev))
	}
	return errorAppender.Error()
}

func ensureEnvvar(ev *Envvar) error {
	if ev.Optional {
		return nil
	}
	errorAppender := errorappender.NewErrorAppender("; ")
	value, found := os.LookupEnv(ev.Name)
	if found == false {
		errorAppender.AppendString("is not defined")
	} else if value == "" {
		errorAppender.AppendString("is empty")
	}

	return errorAppender.Wrap("environment variable " + ev.Name + " ")
}


text:
SUMMARY = "Non-validating SQL parser module"
DESCRIPTION = "sqlparse is a non-validating SQL parser module. It provides \
support for parsing, splitting and formatting SQL statements."
HOMEPAGE = "https://github.com/andialbrecht/sqlparse"
SECTION = "devel/python"

LICENSE = "BSD"
LIC_FILES_CHKSUM = "file://LICENSE;md5=2b136f573f5386001ea3b7b9016222fc"

SRC_URI[md5sum] = "2ce34181d6b7b234c9f3c0ecd1ffb93e"
SRC_URI[sha256sum] = "7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"

export BUILD_SYS
export HOST_SYS

inherit pypi setuptools

SKIP_RECIPE[python-sqlparse] ?= "${@bb.utils.contains('I_SWEAR_TO_MIGRATE_TO_PYTHON3', 'yes', '', 'python2 is out of support for long time, read https://www.python.org/doc/sunset-python-2/ https://python3statement.org/ and if you really have to temporarily use this, then set I_SWEAR_TO_MIGRATE_TO_PYTHON3 to "yes"', d)}"

branch_name: refs/heads/jansa/master

gha_language: BitBake


text:
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package router

import (
	"sync"
	"time"

	"github.com/ava-labs/gecko/utils/constants"

	"github.com/ava-labs/gecko/utils/formatting"

	"github.com/ava-labs/gecko/ids"
	"github.com/ava-labs/gecko/snow/networking/timeout"
	"github.com/ava-labs/gecko/utils/logging"
	"github.com/ava-labs/gecko/utils/timer"
)

const (
	defaultCPUInterval = 5 * time.Second
)

// ChainRouter routes incoming messages from the validator network
// to the consensus engines that the messages are intended for.
// Note that consensus engines are uniquely identified by the ID of the chain
// that they are working on.
type ChainRouter struct {
	log              logging.Logger
	lock             sync.RWMutex
	chains           map[[32]byte]*Handler
	timeouts         *timeout.Manager
	gossiper         *timer.Repeater
	intervalNotifier *timer.Repeater
	closeTimeout     time.Duration
}

// Initialize the router.
//
// When this router receives an incoming message, it cancels the timeout in
// [timeouts] associated with the request that caused the incoming message, if
// applicable.
//
// This router also fires a gossip event every [gossipFrequency] to the engine,
// notifying the engine it should gossip it's accepted set.
func (sr *ChainRouter) Initialize(
	log logging.Logger,
	timeouts *timeout.Manager,
	gossipFrequency time.Duration,
	closeTimeout time.Duration,
) {
	sr.log = log
	sr.chains = make(map[[32]byte]*Handler)
	sr.timeouts = timeouts
	sr.gossiper = timer.NewRepeater(sr.Gossip, gossipFrequency)
	sr.intervalNotifier = timer.NewRepeater(sr.EndInterval, defaultCPUInterval)
	sr.closeTimeout = closeTimeout

	go log.RecoverAndPanic(sr.gossiper.Dispatch)
	go log.RecoverAndPanic(sr.intervalNotifier.Dispatch)
}

// AddChain registers the specified chain so that incoming
// messages can be routed to it
func (sr *ChainRouter) AddChain(chain *Handler) {
	sr.lock.Lock()
	defer sr.lock.Unlock()

	chainID := chain.Context().ChainID
	sr.log.Debug("registering chain %s with chain router", chainID)
	chain.toClose = func() { sr.RemoveChain(chainID) }
	sr.chains[chainID.Key()] = chain
}

// RemoveChain removes the specified chain so that incoming
// messages can't be routed to it
func (sr *ChainRouter) RemoveChain(chainID ids.ID) {
	sr.lock.Lock()
	chain, exists := sr.chains[chainID.Key()]
	if !exists {
		sr.log.Debug("can't remove unknown chain %s", chainID)
		sr.lock.Unlock()
		return
	}
	delete(sr.chains, chainID.Key())
	sr.lock.Unlock()

	chain.Shutdown()

	ticker := time.NewTicker(sr.closeTimeout)
	select {
	case <-chain.closed:
	case <-ticker.C:
		chain.Context().Log.Warn("timed out while shutting down")
	}
	ticker.Stop()
}

// GetAcceptedFrontier routes an incoming GetAcceptedFrontier request from the
// validator with ID [validatorID]  to the consensus engine working on the
// chain with ID [chainID]
func (sr *ChainRouter) GetAcceptedFrontier(validatorID ids.ShortID, chainID ids.ID, requestID uint32, deadline time.Time) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.GetAcceptedFrontier(validatorID, requestID, deadline)
	} else {
		sr.log.Debug("GetAcceptedFrontier(%s, %s, %d) dropped due to unknown chain", validatorID, chainID, requestID)
	}
}

// AcceptedFrontier routes an incoming AcceptedFrontier request from the
// validator with ID [validatorID]  to the consensus engine working on the
// chain with ID [chainID]
func (sr *ChainRouter) AcceptedFrontier(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containerIDs ids.Set) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		if chain.AcceptedFrontier(validatorID, requestID, containerIDs) {
			sr.timeouts.Cancel(validatorID, chainID, requestID)
		}
	} else {
		sr.log.Debug("AcceptedFrontier(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, containerIDs)
	}
}

// GetAcceptedFrontierFailed routes an incoming GetAcceptedFrontierFailed
// request from the validator with ID [validatorID]  to the consensus engine
// working on the chain with ID [chainID]
func (sr *ChainRouter) GetAcceptedFrontierFailed(validatorID ids.ShortID, chainID ids.ID, requestID uint32) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	sr.timeouts.Cancel(validatorID, chainID, requestID)
	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.GetAcceptedFrontierFailed(validatorID, requestID)
	} else {
		sr.log.Error("GetAcceptedFrontierFailed(%s, %s, %d) dropped due to unknown chain", validatorID, chainID, requestID)
	}
}

// GetAccepted routes an incoming GetAccepted request from the
// validator with ID [validatorID]  to the consensus engine working on the
// chain with ID [chainID]
func (sr *ChainRouter) GetAccepted(validatorID ids.ShortID, chainID ids.ID, requestID uint32, deadline time.Time, containerIDs ids.Set) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.GetAccepted(validatorID, requestID, deadline, containerIDs)
	} else {
		sr.log.Debug("GetAccepted(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, containerIDs)
	}
}

// Accepted routes an incoming Accepted request from the validator with ID
// [validatorID]  to the consensus engine working on the chain with ID
// [chainID]
func (sr *ChainRouter) Accepted(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containerIDs ids.Set) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		if chain.Accepted(validatorID, requestID, containerIDs) {
			sr.timeouts.Cancel(validatorID, chainID, requestID)
		}
	} else {
		sr.log.Debug("Accepted(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, containerIDs)
	}
}

// GetAcceptedFailed routes an incoming GetAcceptedFailed request from the
// validator with ID [validatorID]  to the consensus engine working on the
// chain with ID [chainID]
func (sr *ChainRouter) GetAcceptedFailed(validatorID ids.ShortID, chainID ids.ID, requestID uint32) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	sr.timeouts.Cancel(validatorID, chainID, requestID)
	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.GetAcceptedFailed(validatorID, requestID)
	} else {
		sr.log.Error("GetAcceptedFailed(%s, %s, %d) dropped due to unknown chain", validatorID, chainID, requestID)
	}
}

// GetAncestors routes an incoming GetAncestors message from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
// The maximum number of ancestors to respond with is define in snow/engine/commong/bootstrapper.go
func (sr *ChainRouter) GetAncestors(validatorID ids.ShortID, chainID ids.ID, requestID uint32, deadline time.Time, containerID ids.ID) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.GetAncestors(validatorID, requestID, deadline, containerID)
	} else {
		sr.log.Debug("GetAncestors(%s, %s, %d) dropped due to unknown chain", validatorID, chainID, requestID)
	}
}

// MultiPut routes an incoming MultiPut message from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) MultiPut(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containers [][]byte) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	// This message came in response to a GetAncestors message from this node, and when we sent that
	// message we set a timeout. Since we got a response, cancel the timeout.
	if chain, exists := sr.chains[chainID.Key()]; exists {
		if chain.MultiPut(validatorID, requestID, containers) {
			sr.timeouts.Cancel(validatorID, chainID, requestID)
		}
	} else {
		sr.log.Debug("MultiPut(%s, %s, %d, %d) dropped due to unknown chain", validatorID, chainID, requestID, len(containers))
	}
}

// GetAncestorsFailed routes an incoming GetAncestorsFailed message from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) GetAncestorsFailed(validatorID ids.ShortID, chainID ids.ID, requestID uint32) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	sr.timeouts.Cancel(validatorID, chainID, requestID)
	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.GetAncestorsFailed(validatorID, requestID)
	} else {
		sr.log.Error("GetAncestorsFailed(%s, %s, %d) dropped due to unknown chain", validatorID, chainID, requestID)
	}
}

// Get routes an incoming Get request from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) Get(validatorID ids.ShortID, chainID ids.ID, requestID uint32, deadline time.Time, containerID ids.ID) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.Get(validatorID, requestID, deadline, containerID)
	} else {
		sr.log.Debug("Get(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, containerID)
	}
}

// Put routes an incoming Put request from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) Put(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containerID ids.ID, container []byte) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	// This message came in response to a Get message from this node, and when we sent that Get
	// message we set a timeout. Since we got a response, cancel the timeout.
	if chain, exists := sr.chains[chainID.Key()]; exists {
		if chain.Put(validatorID, requestID, containerID, container) {
			sr.timeouts.Cancel(validatorID, chainID, requestID)
		}
	} else if requestID == constants.GossipMsgRequestID {
		sr.log.Verbo("Gossiped Put(%s, %s, %d, %s) dropped due to unknown chain. Container:",
			validatorID, chainID, requestID, containerID, formatting.DumpBytes{Bytes: container},
		)
	} else {
		sr.log.Debug("Put(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, containerID)
		sr.log.Verbo("container:\n%s", formatting.DumpBytes{Bytes: container})
	}
}

// GetFailed routes an incoming GetFailed message from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) GetFailed(validatorID ids.ShortID, chainID ids.ID, requestID uint32) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	sr.timeouts.Cancel(validatorID, chainID, requestID)
	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.GetFailed(validatorID, requestID)
	} else {
		sr.log.Error("GetFailed(%s, %s, %d) dropped due to unknown chain", validatorID, chainID, requestID)
	}
}

// PushQuery routes an incoming PushQuery request from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) PushQuery(validatorID ids.ShortID, chainID ids.ID, requestID uint32, deadline time.Time, containerID ids.ID, container []byte) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.PushQuery(validatorID, requestID, deadline, containerID, container)
	} else {
		sr.log.Debug("PushQuery(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, containerID)
		sr.log.Verbo("container:\n%s", formatting.DumpBytes{Bytes: container})
	}
}

// PullQuery routes an incoming PullQuery request from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) PullQuery(validatorID ids.ShortID, chainID ids.ID, requestID uint32, deadline time.Time, containerID ids.ID) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.PullQuery(validatorID, requestID, deadline, containerID)
	} else {
		sr.log.Debug("PullQuery(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, containerID)
	}
}

// Chits routes an incoming Chits message from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) Chits(validatorID ids.ShortID, chainID ids.ID, requestID uint32, votes ids.Set) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	// Cancel timeout we set when sent the message asking for these Chits
	if chain, exists := sr.chains[chainID.Key()]; exists {
		if chain.Chits(validatorID, requestID, votes) {
			sr.timeouts.Cancel(validatorID, chainID, requestID)
		}
	} else {
		sr.log.Debug("Chits(%s, %s, %d, %s) dropped due to unknown chain", validatorID, chainID, requestID, votes)
	}
}

// QueryFailed routes an incoming QueryFailed message from the validator with ID [validatorID]
// to the consensus engine working on the chain with ID [chainID]
func (sr *ChainRouter) QueryFailed(validatorID ids.ShortID, chainID ids.ID, requestID uint32) {
	sr.lock.RLock()
	defer sr.lock.RUnlock()

	sr.timeouts.Cancel(validatorID, chainID, requestID)
	if chain, exists := sr.chains[chainID.Key()]; exists {
		chain.QueryFailed(validatorID, requestID)
	} else {
		sr.log.Error("QueryFailed(%s, %s, %d) dropped due to unknown chain", validatorID, chainID, requestID)
	}
}

// Shutdown shuts down this router
func (sr *ChainRouter) Shutdown() {
	sr.lock.Lock()
	prevChains := sr.chains
	sr.chains = map[[32]byte]*Handler{}
	sr.lock.Unlock()

	sr.gossiper.Stop()
	sr.intervalNotifier.Stop()

	for _, chain := range prevChains {
		chain.Shutdown()
	}

	ticker := time.NewTicker(sr.closeTimeout)
	timedout := false
	for _, chain := range prevChains {
		select {
		case <-chain.closed:
		case <-ticker.C:
			timedout = true
		}
	}
	if timedout {
		sr.log.Warn("timed out while shutting down the chains")
	}
	ticker.Stop()
}

// Gossip accepted containers
func (sr *ChainRouter) Gossip() {
	sr.lock.Lock()
	defer sr.lock.Unlock()

	for _, chain := range sr.chains {
		chain.Gossip()
	}
}

// EndInterval notifies the chains that the current CPU interval has ended
func (sr *ChainRouter) EndInterval() {
	sr.lock.Lock()
	defer sr.lock.Unlock()

	for _, chain := range sr.chains {
		chain.endInterval()
	}
}


text:
@inproceedings{vankadara2020optimality,
  title={On the optimality of kernels for high-dimensional clustering},
  author={Vankadara, Leena C and Ghoshdastidar, Debarghya},
  booktitle={International Conference on Artificial Intelligence and Statistics},
  pages={2185--2195},
  year={2020}
}


text:
// +build darwin freebsd linux netbsd openbsd

package logs

import (
	"io"
	"os"
	"syscall"
	"unsafe"
)

func isTerminal(fd uintptr) bool {
	var termios syscall.Termios
	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
	return err == 0
}

func checkIfTerminal(w io.Writer) bool  {
	switch v := w.(type) {
	case *os.File:
		return isTerminal(v.Fd())
	default:
		return false
	}
}

func stderr() io.Writer {
	return os.Stderr
}

repository: linxlib/logs

repo_name: linxlib/logs


text:
@inproceedings{guo1,
    author = {Guo, Philip and Kim, Juho and Rubin, Rob},
    year = {2014},
    month = {03},
    pages = {41-50},
    title = {How video production affects student engagement: An empirical study of MOOC videos},
    doi = {10.1145/2556325.2566239}
}

@article{wood1,
author = {Wood, David and Ross, Gail},
year = {2006},
month = {12},
pages = {89 - 100},
title = {The Role of Tutoring in Problem Solving},
volume = {17},
journal = {Journal of Child Psychology and Psychiatry},
doi = {10.1111/j.1469-7610.1976.tb00381.x}
}

@unpublished{hess1,
author = {Hess, Mark},
year = {2020},
month = {01},
title = {Course Design Reimagined: Using Novice Experience To Teach Expert Knowledge},
}

@unpublished{guida1,
author = {Guida, Carmine},
year = {2020},
month = {01},
title = {High Production Quality on a Low Budget: Videos for Online Courses},
}

@inproceedings{joyner1,
author = {Joyner, David},
year = {2018},
month = {06},
pages = {1-10},
title = {Toward CS1 at scale: building and testing a MOOC-for-credit candidate},
doi = {10.1145/3231644.3231665}
}

@inproceedings{cross1,
author = {Cross, Andrew and Bayyapunedi, Mydhili and Cutrell, Edward and Agarwal, Anant and Thies, William},
year = {2013},
month = {04},
pages = {793-796},
title = {TypeRighting: Combining the benefits of handwriting and typeface in online educational videos},
journal = {Conference on Human Factors in Computing Systems - Proceedings},
doi = {10.1145/2470654.2470766}
}

@article{tackett1,
author = {Tackett, Sean and Slinn, Kyle and Marshall, Tanner and Gaglani, Shiv and Waldman, Vincent and Desai, Rishi},
year = {2018},
month = {01},
pages = {1},
title = {Medical Education Videos for the World: An Analysis of Viewing Patterns for a YouTube Channel},
volume = {93},
journal = {Academic Medicine},
doi = {10.1097/ACM.0000000000002118}
}

@article{leva1,
author = {Levasseur, David and Sawyer, Kanan},
year = {2006},
month = {01},
pages = {101-123},
title = {Pedagogy Meets PowerPoint: A Research Review of the Effects of Computer-Generated Slides in the Classroom},
volume = {6},
journal = {Review of Communication},
doi = {10.1080/15358590600763383}
}

@article{lim1,
title = "Exploring the use of entertainment-education YouTube videos focused on infection prevention and control",
journal = "American Journal of Infection Control",
volume = "46",
number = "11",
pages = "1218 - 1223",
year = "2018",
issn = "0196-6553",
doi = "https://doi.org/10.1016/j.ajic.2018.05.002",
url = "http://www.sciencedirect.com/science/article/pii/S0196655318305753",
author = "Kathryn Lim and Claire Kilpatrick and Julie Storr and Holly Seale",
keywords = "Hand hygiene, Infection control, YouTube, Internet, Health education, Education entertainment, Video, Behavior change",
}

@article{hew1,
title = "Students’ and instructors’ use of massive open online courses (MOOCs): Motivations and challenges",
journal = "Educational Research Review",
volume = "12",
pages = "45 - 58",
year = "2014",
issn = "1747-938X",
doi = "https://doi.org/10.1016/j.edurev.2014.05.001",
url = "http://www.sciencedirect.com/science/article/pii/S1747938X14000128",
author = "Khe Foon Hew and Wing Sum Cheung",
keywords = "MOOC, Massive open online course, Online learning, E-learning, Motivation",
}

@article{hone1,
title = "Exploring the factors affecting MOOC retention: A survey study",
journal = "Computers & Education",
volume = "98",
pages = "157 - 168",
year = "2016",
issn = "0360-1315",
doi = "https://doi.org/10.1016/j.compedu.2016.03.016",
url = "http://www.sciencedirect.com/science/article/pii/S0360131516300793",
author = "Kate S. Hone and Ghada R. El Said",
keywords = "Massive Open Online Courses (MOOCs), Distance education, Telelearning",
}

  @inproceedings{kim1,
 author = {Kim, Juho and Guo, Philip J. and Seaton, Daniel T. and Mitros, Piotr and Gajos, Krzysztof Z. and Miller, Robert C.},
 title = {Understanding In-Video Dropouts and Interaction Peaks In online Lecture Videos},
 year = {2014},
 isbn = {9781450326698},
 publisher = {Association for Computing Machinery},
 address = {New York, NY, USA},
 url = {https://doi.org/10.1145/2556325.2566237},
 doi = {10.1145/2556325.2566237},
 booktitle = {Proceedings of the First ACM Conference on Learning @ Scale Conference},
 pages = {31–40},
 numpages = {10},
 keywords = {video analysis, mooc, interaction peaks, in-video dropout, online education, peak detection.},
 location = {Atlanta, Georgia, USA},
 series = {L@S ’14}
}

  @inproceedings{kiz1,
 author = {Kizilcec, Ren\'{e} F. and Piech, Chris and Schneider, Emily},
 title = {Deconstructing Disengagement: Analyzing Learner Subpopulations in Massive Open Online Courses},
 year = {2013},
 isbn = {9781450317856},
 publisher = {Association for Computing Machinery},
 address = {New York, NY, USA},
 url = {https://doi.org/10.1145/2460296.2460330},
 doi = {10.1145/2460296.2460330},
 booktitle = {Proceedings of the Third International Conference on Learning Analytics and Knowledge},
 pages = {170–179},
 numpages = {10},
 keywords = {learner engagement patterns, learning analytics, MOOCs},
 location = {Leuven, Belgium},
 series = {LAK ’13}
}

  @inproceedings{houston1,
 author = {Houston, Stacey L. and Brady, Katherine and Narasimham, Gayathri and Fisher, Douglas},
 title = {Pass the Idea Please: The Relationship between Network Position, Direct Engagement, and Course Performance in MOOCs},
 year = {2017},
 isbn = {9781450344500},
 publisher = {Association for Computing Machinery},
 address = {New York, NY, USA},
 url = {https://doi.org/10.1145/3051457.3054008},
 doi = {10.1145/3051457.3054008},
 booktitle = {Proceedings of the Fourth (2017) ACM Conference on Learning @ Scale},
 pages = {295–298},
 numpages = {4},
 keywords = {social network analysis, moocs, course performance},
 location = {Cambridge, Massachusetts, USA},
 series = {L@S ’17}
}

@article{yuechen1,
author = {Yue Chen and Qin Gao and Quan Yuan and Yuanli Tang},
title = {Facilitating Students’ Interaction in MOOCs through Timeline-Anchored Discussion},
journal = {International Journal of Human–Computer Interaction},
volume = {35},
number = {19},
pages = {1781-1799},
year  = {2019},
publisher = {Taylor & Francis},
doi = {10.1080/10447318.2019.1574056},

URL = {
        https://doi.org/10.1080/10447318.2019.1574056
},
eprint = {
        https://doi.org/10.1080/10447318.2019.1574056
}
}

 @inproceedings{pandey1,
 author = {Pandey, Vineet and Kotturi, Yasmine and Kulkarni, Chinmay and Bernstein, Michael S. and Klemmer, Scott},
 title = {Connecting Stories and Pedagogy Increases Participant Engagement in Discussions},
 year = {2015},
 isbn = {9781450334112},
 publisher = {Association for Computing Machinery},
 address = {New York, NY, USA},
 url = {https://doi.org/10.1145/2724660.2728670},
 doi = {10.1145/2724660.2728670},
 booktitle = {Proceedings of the Second (2015) ACM Conference on Learning @ Scale},
 pages = {253–256},
 numpages = {4},
 keywords = {discussion, small groups, synchronous collaboration, video},
 location = {Vancouver, BC, Canada},
 series = {L@S ’15}
}


text:
package plugin_test

import (
	"testing"

	"github.com/codefluence-x/altair/mock"
	"github.com/codefluence-x/altair/plugin"
	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
)

func TestPlugin(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	oauthAccessTokenModel := mock.NewMockOauthAccessTokenModel(mockCtrl)

	assert.NotPanics(t, func() {
		plugin.DownStream().Oauth(oauthAccessTokenModel)
	})
}

repository: aliffauzi/altair

repo_name: aliffauzi/altair


text:
package engine

import (
	"fmt"
	"oh-my-posh/color"
	"oh-my-posh/console"
	"oh-my-posh/platform"
	"oh-my-posh/shell"
	"oh-my-posh/template"
	"strings"
	"time"
)

type Engine struct {
	Config       *Config
	Env          platform.Environment
	Writer       color.Writer
	Ansi         *color.Ansi
	ConsoleTitle *console.Title
	Plain        bool

	console           strings.Builder
	currentLineLength int
	rprompt           string
	rpromptLength     int
}

func (e *Engine) write(text string) {
	e.console.WriteString(text)
}

func (e *Engine) writeANSI(text string) {
	if e.Plain {
		return
	}
	e.console.WriteString(text)
}

func (e *Engine) string() string {
	return e.console.String()
}

func (e *Engine) canWriteRPrompt(rprompt bool) bool {
	if rprompt && (e.rprompt == "" || e.Plain) {
		return false
	}
	consoleWidth, err := e.Env.TerminalWidth()
	if err != nil || consoleWidth == 0 {
		return true
	}
	promptWidth := e.currentLineLength
	availableSpace := consoleWidth - promptWidth
	// spanning multiple lines
	if availableSpace < 0 {
		overflow := promptWidth % consoleWidth
		availableSpace = consoleWidth - overflow
	}
	promptBreathingRoom := 5
	if rprompt {
		promptBreathingRoom = 30
	}
	canWrite := (availableSpace - e.rpromptLength) >= promptBreathingRoom
	return canWrite
}

func (e *Engine) PrintPrimary() string {
	for _, block := range e.Config.Blocks {
		e.renderBlock(block)
	}
	if len(e.Config.ConsoleTitleTemplate) > 0 {
		e.writeANSI(e.ConsoleTitle.GetTitle())
	}
	e.writeANSI(e.Ansi.ColorReset())
	if e.Config.FinalSpace {
		e.write(" ")
	}
	e.printPWD()
	return e.print()
}

func (e *Engine) printPWD() {
	if len(e.Config.PWD) == 0 && !e.Config.OSC99 {
		return
	}
	cwd := e.Env.Pwd()
	// Backwards compatibility for deprecated OSC99
	if e.Config.OSC99 {
		e.writeANSI(e.Ansi.ConsolePwd(color.OSC99, "", cwd))
		return
	}
	// Allow template logic to define when to enable the PWD (when supported)
	tmpl := &template.Text{
		Template: e.Config.PWD,
		Env:      e.Env,
	}
	pwdType, err := tmpl.Render()
	if err != nil || len(pwdType) == 0 {
		return
	}
	host, _ := e.Env.Host()
	e.writeANSI(e.Ansi.ConsolePwd(pwdType, host, cwd))
}

func (e *Engine) newline() {
	e.write("\n")
	e.currentLineLength = 0
}

func (e *Engine) shouldFill(block *Block, length int) (string, bool) {
	if len(block.Filler) == 0 {
		return "", false
	}
	terminalWidth, err := e.Env.TerminalWidth()
	if err != nil || terminalWidth == 0 {
		return "", false
	}
	padLength := terminalWidth - e.currentLineLength - length
	if padLength <= 0 {
		return "", false
	}
	e.Writer.Write("", "", block.Filler)
	filler, lenFiller := e.Writer.String()
	e.Writer.Reset()
	if lenFiller == 0 {
		return "", false
	}
	repeat := padLength / lenFiller
	return strings.Repeat(filler, repeat), true
}

func (e *Engine) renderBlock(block *Block) {
	defer func() {
		// Due to a bug in PowerShell, the end of the line needs to be cleared.
		// If this doesn't happen, the portion after the prompt gets colored in the background
		// color of the line above the new input line. Clearing the line fixes this,
		// but can hopefully one day be removed when this is resolved natively.
		if e.Env.Shell() == shell.PWSH || e.Env.Shell() == shell.PWSH5 {
			e.writeANSI(e.Ansi.ClearAfter())
		}
	}()
	// when in bash, for rprompt blocks we need to write plain
	// and wrap in escaped mode or the prompt will not render correctly
	if e.Env.Shell() == shell.BASH && (block.Type == RPrompt || block.Alignment == Right) {
		block.InitPlain(e.Env, e.Config)
	} else {
		block.Init(e.Env, e.Writer, e.Ansi)
	}
	if !block.Enabled() {
		return
	}
	if block.Newline {
		e.newline()
	}
	switch block.Type {
	// This is deprecated but leave if to not break current configs
	// It is encouraged to used "newline": true on block level
	// rather than the standalone the linebreak block
	case LineBreak:
		e.newline()
	case Prompt:
		if block.VerticalOffset != 0 {
			e.writeANSI(e.Ansi.ChangeLine(block.VerticalOffset))
		}

		if block.Alignment == Left {
			text, length := block.RenderSegments()
			e.currentLineLength += length
			e.write(text)
			return
		}

		if block.Alignment != Right {
			return
		}

		text, length := block.RenderSegments()
		e.rpromptLength = length

		if !e.canWriteRPrompt(false) {
			switch block.Overflow {
			case Break:
				e.newline()
			case Hide:
				// make sure to fill if needed
				if padText, OK := e.shouldFill(block, 0); OK {
					e.write(padText)
				}
				return
			}
		}

		if padText, OK := e.shouldFill(block, length); OK {
			// in this case we can print plain
			e.write(padText)
			e.write(text)
			return
		}
		// this can contain ANSI escape sequences
		ansi := e.Ansi
		if e.Env.Shell() == shell.BASH {
			ansi = &color.Ansi{}
			ansi.InitPlain()
		}
		prompt := ansi.CarriageForward()
		prompt += ansi.GetCursorForRightWrite(length, block.HorizontalOffset)
		prompt += text
		e.currentLineLength = 0
		if e.Env.Shell() == shell.BASH {
			prompt = e.Ansi.FormatText(prompt)
		}
		e.write(prompt)
	case RPrompt:
		e.rprompt, e.rpromptLength = block.RenderSegments()
	}
}

// debug will loop through your config file and output the timings for each segments
func (e *Engine) PrintDebug(startTime time.Time, version string) string {
	var segmentTimings []*SegmentTiming
	largestSegmentNameLength := 0
	e.write(fmt.Sprintf("\n\x1b[1mVersion:\x1b[0m %s\n", version))
	e.write("\n\x1b[1mSegments:\x1b[0m\n\n")
	// console title timing
	titleStartTime := time.Now()
	title := e.ConsoleTitle.GetTitle()
	title = strings.TrimPrefix(title, "\x1b]0;")
	title = strings.TrimSuffix(title, "\a")
	segmentTiming := &SegmentTiming{
		name:       "ConsoleTitle",
		nameLength: 12,
		active:     len(e.Config.ConsoleTitleTemplate) > 0,
		text:       title,
		duration:   time.Since(titleStartTime),
	}
	segmentTimings = append(segmentTimings, segmentTiming)
	// loop each segments of each blocks
	for _, block := range e.Config.Blocks {
		block.Init(e.Env, e.Writer, e.Ansi)
		longestSegmentName, timings := block.Debug()
		segmentTimings = append(segmentTimings, timings...)
		if longestSegmentName > largestSegmentNameLength {
			largestSegmentNameLength = longestSegmentName
		}
	}

	// pad the output so the tabs render correctly
	largestSegmentNameLength += 7
	for _, segment := range segmentTimings {
		duration := segment.duration.Milliseconds()
		segmentName := fmt.Sprintf("%s(%t)", segment.name, segment.active)
		e.write(fmt.Sprintf("%-*s - %3d ms - %s\n", largestSegmentNameLength, segmentName, duration, segment.text))
	}
	e.write(fmt.Sprintf("\n\x1b[1mRun duration:\x1b[0m %s\n", time.Since(startTime)))
	e.write(fmt.Sprintf("\n\x1b[1mCache path:\x1b[0m %s\n", e.Env.CachePath()))
	e.write(fmt.Sprintf("\n\x1b[1mConfig path:\x1b[0m %s\n", e.Env.Flags().Config))
	e.write("\n\x1b[1mLogs:\x1b[0m\n\n")
	e.write(e.Env.Logs())
	return e.string()
}

func (e *Engine) print() string {
	switch e.Env.Shell() {
	case shell.ZSH:
		if !e.Env.Flags().Eval {
			break
		}
		// escape double quotes contained in the prompt
		prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(e.string(), `"`, `\"`))
		prompt += fmt.Sprintf("\nRPROMPT=\"%s\"", e.rprompt)
		return prompt
	case shell.PWSH, shell.PWSH5, shell.PLAIN, shell.NU:
		if !e.canWriteRPrompt(true) {
			break
		}
		e.write(e.Ansi.SaveCursorPosition())
		e.write(e.Ansi.CarriageForward())
		e.write(e.Ansi.GetCursorForRightWrite(e.rpromptLength, 0))
		e.write(e.rprompt)
		e.write(e.Ansi.RestoreCursorPosition())
	case shell.BASH:
		if !e.canWriteRPrompt(true) {
			break
		}
		// in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly
		// see https://github.com/JanDeDobbeleer/oh-my-posh/pull/2398
		ansi := &color.Ansi{}
		ansi.InitPlain()
		prompt := ansi.SaveCursorPosition()
		prompt += ansi.CarriageForward()
		prompt += ansi.GetCursorForRightWrite(e.rpromptLength, 0)
		prompt += e.rprompt
		prompt += ansi.RestoreCursorPosition()
		prompt = e.Ansi.FormatText(prompt)
		e.write(prompt)
	}
	return e.string()
}

func (e *Engine) PrintTooltip(tip string) string {
	tip = strings.Trim(tip, " ")
	var tooltip *Segment
	for _, tp := range e.Config.Tooltips {
		if !tp.shouldInvokeWithTip(tip) {
			continue
		}
		tooltip = tp
	}
	if tooltip == nil {
		return ""
	}
	if err := tooltip.mapSegmentWithWriter(e.Env); err != nil {
		return ""
	}
	if !tooltip.writer.Enabled() {
		return ""
	}
	tooltip.Enabled = true
	// little hack to reuse the current logic
	block := &Block{
		Alignment: Right,
		Segments:  []*Segment{tooltip},
	}
	switch e.Env.Shell() {
	case shell.ZSH, shell.CMD, shell.FISH:
		block.Init(e.Env, e.Writer, e.Ansi)
		if !block.Enabled() {
			return ""
		}
		text, _ := block.RenderSegments()
		return text
	case shell.PWSH, shell.PWSH5:
		block.InitPlain(e.Env, e.Config)
		if !block.Enabled() {
			return ""
		}
		text, length := block.RenderSegments()
		e.write(e.Ansi.ClearAfter())
		e.write(e.Ansi.CarriageForward())
		e.write(e.Ansi.GetCursorForRightWrite(length, 0))
		e.write(text)
		return e.string()
	}
	return ""
}

type ExtraPromptType int

const (
	Transient ExtraPromptType = iota
	Valid
	Error
	Secondary
	Debug
)

func (e *Engine) PrintExtraPrompt(promptType ExtraPromptType) string {
	// populate env with latest context
	e.Env.LoadTemplateCache()
	var prompt *Segment
	switch promptType {
	case Debug:
		prompt = e.Config.DebugPrompt
	case Transient:
		prompt = e.Config.TransientPrompt
	case Valid:
		prompt = e.Config.ValidLine
	case Error:
		prompt = e.Config.ErrorLine
	case Secondary:
		prompt = e.Config.SecondaryPrompt
	}
	if prompt == nil {
		prompt = &Segment{}
	}
	getTemplate := func(template string) string {
		if len(template) != 0 {
			return template
		}
		switch promptType { //nolint: exhaustive
		case Debug:
			return "[DBG]: "
		case Transient:
			return "{{ .Shell }}> "
		case Secondary:
			return "> "
		default:
			return ""
		}
	}
	tmpl := &template.Text{
		Template: getTemplate(prompt.Template),
		Env:      e.Env,
	}
	promptText, err := tmpl.Render()
	if err != nil {
		promptText = err.Error()
	}
	foreground := prompt.ForegroundTemplates.FirstMatch(nil, e.Env, prompt.Foreground)
	background := prompt.BackgroundTemplates.FirstMatch(nil, e.Env, prompt.Background)
	e.Writer.SetColors(background, foreground)
	e.Writer.Write(background, foreground, promptText)
	switch e.Env.Shell() {
	case shell.ZSH:
		// escape double quotes contained in the prompt
		str, _ := e.Writer.String()
		if promptType == Transient {
			prompt := fmt.Sprintf("PS1=\"%s\"", strings.ReplaceAll(str, "\"", "\"\""))
			// empty RPROMPT
			prompt += "\nRPROMPT=\"\""
			return prompt
		}
		return str
	case shell.PWSH, shell.PWSH5, shell.CMD, shell.BASH, shell.FISH, shell.NU:
		str, _ := e.Writer.String()
		return str
	}
	return ""
}

func (e *Engine) PrintRPrompt() string {
	filterRPromptBlock := func(blocks []*Block) *Block {
		for _, block := range blocks {
			if block.Type == RPrompt {
				return block
			}
		}
		return nil
	}
	block := filterRPromptBlock(e.Config.Blocks)
	if block == nil {
		return ""
	}
	block.Init(e.Env, e.Writer, e.Ansi)
	if !block.Enabled() {
		return ""
	}
	text, length := block.RenderSegments()
	e.rpromptLength = length
	return text
}

repository: JustinGrote/oh-my-posh

repo_name: JustinGrote/oh-my-posh


text:
SUMMARY = "RetroArch joypad autoconfig files"
DESCRIPTION = "Autoconfig files included in this repository are used to \
recognize input devices and automatically setup default mappings between \
the physical device and Retropad virtual controller."

HOMEPAGE = "https://www.retroarch.com/"
BUGTRACKER = "https://github.com/libretro/retroarch-joypad-autoconfig/issues"

LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://COPYING;md5=459277d80461c2908b4cf14949f8dcd5"

SRC_URI = "gitsm://github.com/libretro/retroarch-joypad-autoconfig.git;protocol=https;branch=master"

inherit retroarch-allarch

FILES:${PN} += "${RETROARCH_AUTOCONFIG_DIR}"

do_patch() {
  rm -f ${S}/Makefile
  rm -f ${S}/configure
}

do_install() {
  install -m 0755 -d ${D}${RETROARCH_AUTOCONFIG_DIR}
  cp -R --no-dereference --preserve=mode,links -v ${S}/* ${D}${RETROARCH_AUTOCONFIG_DIR}
}


text:
package controllers

import (
	"Kapi/config"
	"Kapi/services"
	"Kapi/utils"
	"Kapi/validator"
	"github.com/kataras/iris"
	"gopkg.in/validator.v2"
	"net/http"
	"time"
)

type UserController struct {
	Ctx iris.Context
	UserService services.IUserService
}

func (uc *UserController) PostLogin() {
	loginValidator := new(validators.LoginValidator)
	dec := utils.NewDecoder(&utils.DecoderOptions{TagName:"kapi"})
	if err := dec.Decode(uc.Ctx.FormValues(),loginValidator); err != nil {
		utils.ErrorWithCode(err,"PostEmail",400,uc.Ctx)
		return
	}
	if err := validator.Validate(loginValidator); err != nil {
		utils.ErrorWithCode(err,"PostEmail",400,uc.Ctx)
		return
	}
	/* 校验器，没错这些都是校验器 */
	token, err := uc.UserService.LoginByEmail(loginValidator.Email,loginValidator.Password)
	if err != nil {
		utils.ErrorWithError(err,"PostEmail,",uc.Ctx)
		return
	}
	/* 登陆业务，返回token */
	AppConfig, err := config.GetConfig(utils.RootPath()+"/config/config.json")
	if err != nil {
		utils.ErrorWithCode(err,"PostEmail",400,uc.Ctx)
		return
	}
	cookie := &http.Cookie{
		Name:"token",
		Value:token,
		Expires:time.Now().Add(time.Duration(AppConfig.SecurityExpiresIn)),
	}
	uc.Ctx.SetCookie(cookie)
	/* 获取全局配置并且设置token于Cookie */
	uc.Ctx.JSON(utils.MakeDefaultRes(1,"登陆成功！",nil))
	/* 返回 */
}

func (uc *UserController) PostRegister() {
	registeValidator := new(validators.RegisterValidator)
	dec := utils.NewDecoder(&utils.DecoderOptions{TagName:"kapi"})
	if err := dec.Decode(uc.Ctx.FormValues(),registeValidator); err != nil {
		utils.ErrorWithCode(err,"PostRegister",400,uc.Ctx)
		return
	}
	if err := validator.Validate(registeValidator); err != nil {
		utils.ErrorWithCode(err,"PostRegister",400,uc.Ctx)
		return
	}
	/* 校验器，没错这些都是校验器 */
	ip := uc.Ctx.RemoteAddr()
	_, err := uc.UserService.RegisterByEmail(registeValidator.Username,registeValidator.Email,registeValidator.Password,ip)
	if err != nil {
		utils.ErrorWithError(err,"PostRegister",uc.Ctx)
		return
	}
	/* 注册 */
	uc.Ctx.JSON(utils.MakeDefaultRes(1,"注册成功！",nil))
	/* 返回 */
}

repository: man-fish/kapi

repo_name: man-fish/kapi


text:
SUMMARY = "Linux microPlatform image running Pelion Edge"

require recipes-samples/images/lmp-image-common.inc

require recipes-samples/images/lmp-feature-docker.inc
require recipes-samples/images/lmp-feature-wifi.inc
require recipes-samples/images/lmp-feature-sbin-path-helper.inc

IMAGE_FEATURES[validitems] += "tools-debug tools-sdk"
IMAGE_FEATURES += "package-management ssh-server-openssh"
#IMAGE_LINGUAS = "en-us

IMAGE_OVERHEAD_FACTOR = "2"

DEPENDS += "deviceos-users"

CORE_IMAGE_BASE_INSTALL += " \
    kernel-modules \
    networkmanager-nmcli \
    git \
    vim \
    rng-tools \
    haveged \
    packagegroup-core-full-cmdline-utils \
    packagegroup-core-full-cmdline-extended \
    packagegroup-core-full-cmdline-multiuser \
"

CORE_OS = " \
openssh \
packagegroup-core-boot \
packagegroup-core-full-cmdline \
"

#mbed-edge-core is currently dependant on deviceos-users "developer"
PELION_BASE_REQUIRED = " \
deviceos-users \
virtual/mbed-edge-core \
identity-tool \
path-set \
pelion-version \
"
PELION_BASE_OPTIONAL = " \
mbed-fcce \
"

PELION_SYSTEMS_MANAGEMENT = "\
edge-proxy \
maestro \
devicedb \
info-tool \
relay-term \
fluentbit \
"

PELION_PROTOCOL_TRANSLATION = " \
mbed-edge-examples \
"

PELION_CONTAINER_ORCHESTRATION = " \
kubelet \
edge-proxy \
"

PELION_TESTING = " \
git \
panic \
"

PARSEC_SERVICE = " \
parsec-service-tpm \
"

PARSEC_TOOL = " \
parsec-tool \
"

SOFTWARE_TPM = " \
swtpm-service \
tpm2-tools \
"

IMAGE_INSTALL += " \
${CORE_OS} \
${PELION_BASE_REQUIRED} \
${PELION_BASE_OPTIONAL} \
${PELION_PROTOCOL_TRANSLATION} \
${PELION_SYSTEMS_MANAGEMENT} \
${PELION_CONTAINER_ORCHESTRATION} \
${PELION_TESTING} \
${MACHINE_EXTRA_RRECOMMENDS} \
${PARSEC_SERVICE} \
${PARSEC_TOOL} \
${SOFTWARE_TPM} \
"

# Create a parsec user and then set permissions on the parsec components to control access.
# Create the parsec user.
inherit extrausers
EXTRA_USERS_PARAMS += "\
    useradd parsec;\
"

# modify the ownership of the folders and files that only the parsec user needs access to.

ROOTFS_POSTPROCESS_COMMAND_append = " \
  setup_parsec_files; \
"
setup_parsec_files() {
    chown -R parsec:parsec ${IMAGE_ROOTFS}/etc/parsec
    chown -R parsec:parsec ${IMAGE_ROOTFS}/usr/libexec/parsec
    chown parsec:parsec ${IMAGE_ROOTFS}/usr/bin/swtpm.sh
}
set_local_timezone() {
    ln -sf /usr/share/zoneinfo/EST5EDT ${IMAGE_ROOTFS}/etc/localtime
}

disable_bootlogd() {
    echo BOOTLOGD_ENABLE=no > ${IMAGE_ROOTFS}/etc/default/bootlogd
}

ROOTFS_POSTPROCESS_COMMAND += " \
    set_local_timezone ; \
    disable_bootlogd ; \
"

export IMAGE_BASENAME = "console-image-lmp"

# SolidRun Hummingboard Pulse has a Murata 1MW wifi/bt module which uses custom recipes
# linux-firmware-cyw-fmac-fw, linux-firmware-cyw-fmac-nvram and linux-firmware-cyw-bt-patch.
# Make sure we avoid default linux bcm43455 firmware
CORE_IMAGE_BASE_INSTALL_remove_imx8mmsolidrun = " \
    linux-firmware-bcm43455 \
"

repository: kjbracey/meta-pelion-edge

repo_name: kjbracey/meta-pelion-edge


text:
include_guard(GLOBAL)

if (NOT DEFINED CMSISOS_TARGET)
	message(FATAL_ERROR "Please define CMSISOS_TARGET before including the cmsis::os package")
endif()

if (NOT DEFINED CMSISOS_COMPILER)
	message(FATAL_ERROR "Please define CMSISOS_COMPILER before including the cmsis::os package")
endif()

project(cmsis-os)

add_library(cmsis-os INTERFACE)
add_library(cmsis::os ALIAS cmsis-os)

target_sources(cmsis-os
	INTERFACE
	${CMAKE_CURRENT_LIST_DIR}/src/cmsis_os1.c
	${CMAKE_CURRENT_LIST_DIR}/src/os_systick.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/config/RTX_Config.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_delay.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_evflags.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_evr.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_kernel.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_lib.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_memory.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_mempool.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_msgqueue.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_mutex.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_semaphore.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_system.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_thread.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/rtx_timer.c
	${CMAKE_CURRENT_LIST_DIR}/rtx/source/${CMSISOS_COMPILER}/irq_${CMSISOS_TARGET}.s
)

target_include_directories(cmsis-os
	INTERFACE
	${CMAKE_CURRENT_LIST_DIR}/inc
	${CMAKE_CURRENT_LIST_DIR}/rtx/include
)

repository: MasuodSamarin/common

repo_name: MasuodSamarin/common


text:
@article{Pappas2018GILEAG,
  title={GILE: A Generalized Input-Label Embedding for Text Classification},
  author={Nikolaos Pappas and Jon C. Henderson},
  journal={Transactions of the Association for Computational Linguistics},
  year={2018},
  volume={7},
  pages={139-155}
}

url: https://raw.githubusercontent.com/Hugh-Shi/DL-NLP-Readings/924e4d189e5660c5b5d4854278f3df755ae2231d/Bibtex/GILE - A Generalized Input-Label Embedding for Text Classification.bib

repository: Hugh-Shi/DL-NLP-Readings

repo_name: Hugh-Shi/DL-NLP-Readings


text:
@inproceedings{zhao2021lightguardian,
 booktitle = {18th USENIX Symposium on Networked Systems Design and Implementation (NSDI 21)},
 month = {April},
 publisher = {USENIX Association},
 title = {LightGuardian: A Full-Visibility, Lightweight, In-band Telemetry System Using Sketchlets},
 author={Zhao, Yikai and Yang, Kaicheng and Liu, Zirui and Yang, Tong and Wang, Ruixin and others},
 url = {https://www.usenix.org/conference/nsdi21/presentation/zhao},
 year = {2021}
}

repository: M-Arimase/academic-kickstart-ZiruiLiu

repo_name: M-Arimase/academic-kickstart-ZiruiLiu


text:
package chat

import (
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"os"

	"github.com/nu7hatch/gouuid"

	"golang.org/x/net/websocket"
)

// Server server context
type Server struct {
	clients *ClientRegistry
	quit    chan bool
	Config  *Config
	Logger  *log.Logger
}

// Config is used to configure Server
type Config struct {
	Port   int
	Logger *log.Logger
}

// RawFrame Represets the raw data from a frame
type RawFrame struct {
	FromID   string `json:"fromID"`
	FromName string `json:"fromName"`
	To       string `json:"to"`
	Data     string `json:"data"`
	Action   string `json:"action"`
}

func (f *RawFrame) String() string {
	return fmt.Sprintf("RawFrame{Action: %s, To: %s, FromID: %s, FromName: %s, Data: %s}", f.Action, f.To, f.FromID, f.FromName, f.Data)
}

// Frame is an incoming or outgoing Frame
type Frame struct {
	err        error
	From       string `json:"from"`
	FromName   string `json:"fromName"`
	To         string `json:"to"`
	Data       string `json:"data"`
	Action     string `json:"action"`
	FromClient *Client
	ToClient   *Client
}

func (f *Frame) String() string {
	return fmt.Sprintf("Frame{Action: %s, To: %s, From: %s, Data: %s}", f.Action, f.To, f.From, f.Data)
}

// NewServer constructs a Server
func NewServer(config *Config) *Server {
	server := Server{}
	server.clients = NewClientRegistry()
	server.quit = make(chan bool)
	if config == nil {
		server.Config = &Config{Port: 8080}
	} else {
		server.Config = config
	}
	if server.Config.Logger == nil {
		server.Logger = log.New(os.Stdout, "Server: ", log.Lshortfile)
	} else {
		server.Logger = server.Config.Logger
	}
	return &server
}

// Start starts the chat server
func (server *Server) Start() (chan bool, net.Listener, error) {
	http.Handle("/websocket", NewWebsocketHTTPHandler(server))
	http.Handle("/echo", websocket.Handler(echoHandler))
	http.Handle("/", http.FileServer(http.Dir("webroot")))
	server.Logger.Println("Starting server on port 8080...")

	finished := make(chan bool)
	listener, err := listen(server, server.Config.Port, finished)
	if err != nil {
		server.Logger.Printf("Failed to start server: %v\n", err)
		return nil, listener, err
	}
	server.Logger.Println("Server started")
	return finished, listener, nil
}

func receiveFrame(cli *Client, server *Server) error {
	frame := &Frame{FromClient: cli}
	rawFrame := RawFrame{}
	err := websocket.JSON.Receive(cli.Conn, &rawFrame)
	frame.Data = rawFrame.Data
	frame.Action = rawFrame.Action
	frame.To = rawFrame.To
	server.Logger.Println("Incoming message")
	return handleIncomingMessage(server, frame, err)
}

func allClientsExceptID(server *Server, id string) []*Client {
	var chosenClients []*Client
	for _, cli := range server.AllClients() {
		if cli.ID != id {
			chosenClients = append(chosenClients, cli)
		}
	}
	return chosenClients
}

func calculateReceivers(msg *Message, server *Server) []*Client {
	if msg.ToStr == "all" {
		return server.AllClients()
	} else if msg.To == nil {
		return []*Client{}
	}
	return []*Client{msg.To}
}

func handleSetName(server *Server, frame *Frame) error {
	frame.FromClient.Name = frame.Data
	outMsg := Frame{
		To:       frame.FromClient.ID,
		FromName: "auto-reply",
		Data:     "Welcome " + frame.FromClient.Name,
	}
	err := websocket.JSON.Send(frame.FromClient.Conn, &outMsg)
	if err != nil {
		server.Logger.Println("Failed to send message: " + err.Error())
		return err
	}
	for _, cli := range allClientsExceptID(server, frame.FromClient.ID) {
		server.Logger.Println("Sending new user notification to client name=" + cli.Name)
		outMsg := Frame{
			To:       cli.ID,
			FromName: "auto-reply",
			Data:     frame.FromClient.Name + " has joined",
		}
		err = websocket.JSON.Send(cli.Conn, &outMsg)
		if err != nil {
			server.Logger.Println("Failed to send message: " + err.Error())
			return err
		}
	}
	return err
}

func sendSystemMessage(server *Server, to *Client, msg string) error {
	msgFrame := &Frame{
		ToClient: to,
		To:       to.ID,
		FromName: "auto-reply",
		Data:     msg,
	}
	return msgFrame.Send(server)
}

func sendRegularMessage(server *Server, from *Client, to *Client, msg string) error {
	server.Logger.Printf("Sending regular message: %v\n", msg)
	msgFrame := &Frame{
		From:       from.ID,
		FromClient: from,
		FromName:   from.Name,
		ToClient:   to,
		To:         to.ID,
		Data:       msg,
	}
	return msgFrame.Send(server)
}

func handleRegularMessage(server *Server, frame *Frame) error {
	// Determine destination
	msg, err := parseMessage(server, frame)

	if err != nil {
		return sendSystemMessage(server, frame.FromClient, "Error: invalid message format")
	}

	receivers := calculateReceivers(msg, server)
	if len(receivers) == 0 {
		server.Logger.Printf("No receiver found for id=%v\n", frame.To)
	} else {
		for _, recip := range receivers {
			err = sendRegularMessage(server, frame.FromClient, recip, msg.Body)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func handleIncomingMessage(server *Server, frame *Frame, err error) error {
	if err != nil {
		if err == io.EOF {
			server.Logger.Printf("Client closed connection (client.ID=%v): %v\n", frame.FromClient.ID, err)
		} else {
			server.Logger.Printf("Error on receving socket (client.ID=%v): %v\n", frame.FromClient.ID, err)
		}
		server.Logger.Printf("Destroying client and connection.\n")
		server.DestroyClient(frame.FromClient)
		return errors.New("Client failed")
	}

	server.Logger.Printf("Received message. frame: %v\n", frame)

	if frame.Action == "set-name" {
		err = handleSetName(server, frame)
	} else {
		err = handleRegularMessage(server, frame)
	}
	return err
}

func parseMessage(server *Server, frame *Frame) (*Message, error) {
	var to *Client
	var parseError error

	// TODO Better validation
	if frame.To == "" {
		parseError = errors.New("No destination specified")
		to = nil
	}

	msg := Message{Body: frame.Data, From: frame.FromClient, To: to, ToStr: frame.To}
	return &msg, parseError
}

func listen(server *Server, port int, finished chan bool) (net.Listener, error) {
	portStr := fmt.Sprintf(":%d", port)
	listener, err := net.Listen("tcp", portStr)
	if err != nil {
		server.Logger.Printf("Failed to listen on port %v\n", port)
	} else {
		go func() {
			err = http.Serve(listener, nil)
			if err != nil {
				server.Logger.Println("ListenAndServe: " + err.Error())
			}
			finished <- true
		}()
	}
	return listener, err
}

func clientHandler(ws *websocket.Conn, server *Server) {
	client := server.CreateAndRegisterClient(ws)
	for {
		err := receiveFrame(client, server)
		if err != nil {
			break
		}
	}
}

// NewWebsocketHTTPHandler creates an http handler for the websocket handler
func NewWebsocketHTTPHandler(server *Server) http.Handler {
	chatHandler := func(ws *websocket.Conn) {
		clientHandler(ws, server)
	}
	return websocket.Handler(chatHandler)
}

func echoHandler(ws *websocket.Conn) {
	defer ws.Close()
	io.Copy(ws, ws)
}

func createClient(ws *websocket.Conn) *Client {
	u, err := uuid.NewV4()
	if err != nil {
		panic("Failed to create UUID")
	}

	id := u.String()

	client := Client{ID: id, Conn: ws}

	return &client
}

// AllClients returns all clients
func (server *Server) AllClients() []*Client {
	return server.clients.AsArray()
}

// Quit tells the server to stop handling requests
func (server *Server) Quit() {
	server.quit <- true
}

// CreateAndRegisterClient creates and registers a client
func (server *Server) CreateAndRegisterClient(ws *websocket.Conn) *Client {
	client := createClient(ws)
	server.clients.Register(client)

	server.Logger.Printf("Client connected. ID given: %v\n", client.ID)

	return client
}

// DestroyClient removes a client from the registry
func (server *Server) DestroyClient(c *Client) {
	server.clients.accessQueue <- func(clients map[string]*Client) {
		server.Logger.Printf("Removing client from registry: %v\n", c)
		delete(clients, c.ID)
	}
	c.Conn.Close()
}

// Send sends a message to a client
func (f *Frame) Send(server *Server) error {
	rawFrame := RawFrame{
		FromID:   f.FromClient.ID,
		FromName: f.FromClient.Name,
		To:       f.ToClient.ID,
		Data:     f.Data,
	}
	err := websocket.JSON.Send(f.ToClient.Conn, &rawFrame)
	if err != nil {
		server.Logger.Println("Failed to send message: " + err.Error())
		return err
	}
	return nil
}

repository: moxley/chat

repo_name: moxley/chat


text:
package index

import (
	"testing"

	"github.com/xichen2020/eventdb/values/iterator"

	"github.com/golang/mock/gomock"
	"github.com/pilosa/pilosa/roaring"
	"github.com/stretchr/testify/require"
)

func TestAtPositionDocIDSetIteratorForwardOnly(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	bm := roaring.NewBitmap()
	bm.DirectAdd(2)
	bm.DirectAdd(5)
	bm.DirectAdd(7)
	bm.DirectAdd(20)
	bm.DirectAdd(54)
	bm.DirectAdd(89)
	bm.DirectAdd(90)
	bm.DirectAdd(107)

	docIDSetIter := newBitmapBasedDocIDIterator(bm.Iterator())
	mockPositionIt := iterator.NewMockPositionIterator(ctrl)
	gomock.InOrder(
		mockPositionIt.EXPECT().Next().Return(true),
		mockPositionIt.EXPECT().Position().Return(2),
		mockPositionIt.EXPECT().Next().Return(true),
		mockPositionIt.EXPECT().Position().Return(4),
		mockPositionIt.EXPECT().Next().Return(true),
		mockPositionIt.EXPECT().Position().Return(7),
		mockPositionIt.EXPECT().Next().Return(false),
		mockPositionIt.EXPECT().Err().Return(nil),
	)
	atPositionIt := NewAtPositionDocIDSetIterator(docIDSetIter, mockPositionIt)
	defer atPositionIt.Close()

	expected := []int32{7, 54, 107}
	var actual []int32
	for atPositionIt.Next() {
		actual = append(actual, atPositionIt.DocID())
	}
	require.NoError(t, atPositionIt.Err())
	require.Equal(t, expected, actual)
}

func TestAtPositionDocIDSetIteratorSeekable(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	docIDSetIter := NewMockSeekableDocIDSetIterator(ctrl)
	gomock.InOrder(
		docIDSetIter.EXPECT().Next().Return(true),
		docIDSetIter.EXPECT().SeekForward(2).Return(nil),
		docIDSetIter.EXPECT().DocID().Return(int32(7)),
		docIDSetIter.EXPECT().SeekForward(2).Return(nil),
		docIDSetIter.EXPECT().DocID().Return(int32(54)),
		docIDSetIter.EXPECT().SeekForward(3).Return(nil),
		docIDSetIter.EXPECT().DocID().Return(int32(107)),
		docIDSetIter.EXPECT().Close(),
	)

	mockPositionIt := iterator.NewMockPositionIterator(ctrl)
	gomock.InOrder(
		mockPositionIt.EXPECT().Next().Return(true),
		mockPositionIt.EXPECT().Position().Return(2),
		mockPositionIt.EXPECT().Next().Return(true),
		mockPositionIt.EXPECT().Position().Return(4),
		mockPositionIt.EXPECT().Next().Return(true),
		mockPositionIt.EXPECT().Position().Return(7),
		mockPositionIt.EXPECT().Next().Return(false),
		mockPositionIt.EXPECT().Err().Return(nil),
	)
	atPositionIt := NewAtPositionDocIDSetIterator(docIDSetIter, mockPositionIt)
	defer atPositionIt.Close()

	expected := []int32{7, 54, 107}
	var actual []int32
	for atPositionIt.Next() {
		actual = append(actual, atPositionIt.DocID())
	}
	require.NoError(t, atPositionIt.Err())
	require.Equal(t, expected, actual)
}

gha_language: Go