text:
DESCRIPTION = "PAM module which support Kerberos 5 authentication"
AUTHOR = "Frank Cusack <fcusack@fcusack.com>"
SECTION = "libs"
LICENSE = "GPLv1"
DEPENDS = "libpam krb5"
PR = "r1"

DEPENDS="libpam krb5"
RDEPENDS="libpam krb5"

SRC_URI = "file://pam_krb5_fk-1.0.tar.gz \
    file://errno.patch;patch=1 \
    file://gsp_aaa.patch;patch=1 \
    "
S = "${WORKDIR}/pam_krb5_fk-${PV}"

LDFLAGS += "-shared"
EXTRA_OEMAKE = '-e OSLIBS="-lnsl -lresolv -lpam -lcom_err" KRB5LIBS="-lkrb5 -lk5crypto -lkrb5support" INC="" '

do_install () {
    install -m 0755 -d ${D}/lib/security
    install -m 0755 pam_krb5.so.1 ${D}/lib/security
    ln -sf pam_krb5.so.1 ${D}/lib/security/pam_krb5.so
    install -m 0755 -d ${D}/${sysconfdir}
    install -m 0644 ${FILESDIR}/krb5.conf ${D}/${sysconfdir}
    install -m 0644 ${FILESDIR}/krb5.keytab ${D}/${sysconfdir}
}

FILES_${PN}-dbg += "/lib/security/.debug"
FILES_${PN} += "/lib/security ${sysconfdir}"


text:
package cliutil

import (
	"fmt"
	"strconv"
	"strings"

	"gopkg.in/AlecAivazis/survey.v1"
)

func GetYesInput(msg string) (bool, error) {
	var yesAnswer string

	if err := GetStringInputDefault(
		msg,
		&yesAnswer,
		"N",
	); err != nil {
		return false, err
	}
	return strings.ToLower(yesAnswer) == "y", nil
}

func GetStringInputLazyPrompt(msgProvider func() string, value *string) error {
	return GetStringInputDefaultLazyPrompt(msgProvider, value, "")
}

func GetStringInput(msg string, value *string) error {
	return GetStringInputDefault(msg, value, "")
}

func GetStringInputDefaultLazyPrompt(msgProvider func() string, value *string, defaultValue string) error {
	prompt := &survey.Input{Message: msgProvider(), Default: defaultValue}
	if err := AskOne(prompt, value, nil); err != nil {
		return err
	}
	return nil
}

func GetStringInputDefault(msg string, value *string, defaultValue string) error {
	prompt := &survey.Input{Message: msg, Default: defaultValue}
	if err := AskOne(prompt, value, nil); err != nil {
		return err
	}
	return nil
}

func GetUint32Input(msg string, value *uint32) error {
	return GetUint32InputDefault(msg, value, 0)
}

func GetUint32InputDefault(msg string, value *uint32, defaultValue uint32) error {
	var strValue string
	prompt := &survey.Input{Message: msg, Default: strconv.Itoa(int(defaultValue))}
	if err := AskOne(prompt, &strValue, nil); err != nil {
		return err
	}
	val, err := strconv.Atoi(strValue)
	if err != nil {
		return err
	}
	*value = uint32(val)
	return nil
}

func GetBoolInput(msg string, value *bool) error {
	return GetBoolInputDefault(msg, value, false)
}

func GetBoolInputDefault(msg string, value *bool, defaultValue bool) error {
	var strValue string
	defaultValueStr := "N"
	if defaultValue {
		defaultValueStr = "y"
	}
	prompt := &survey.Input{Message: msg + " [y/N]: ", Default: defaultValueStr}
	if err := AskOne(prompt, &strValue, nil); err != nil {
		return err
	}
	*value = strings.ToLower(strValue) == "y"
	return nil
}

func GetStringSliceInputLazyPrompt(msgProvider func() string, value *[]string) error {
	for {
		var entry string
		if err := GetStringInputLazyPrompt(msgProvider, &entry); err != nil {
			return err
		}

		if entry == "" {
			return nil
		}
		*value = append(*value, entry)
	}
}

func GetStringSliceInput(msg string, value *[]string) error {
	for {
		var entry string
		if err := GetStringInput(msg, &entry); err != nil {
			return err
		}

		if entry == "" {
			return nil
		}
		*value = append(*value, entry)
	}
}

func ChooseFromList(message string, choice *string, options []string) error {
	if len(options) == 0 {
		return fmt.Errorf("No options to select from (for prompt: %v)", message)
	}

	question := &survey.Select{
		Message: message,
		Options: options,
	}

	if err := AskOne(question, choice, survey.Required); err != nil {
		// this should not error
		fmt.Println("error with input")
		return err
	}

	return nil
}

func MultiChooseFromList(message string, choices *[]string, options []string) error {
	if len(options) == 0 {
		return fmt.Errorf("No options to select from (for prompt: %v)", message)
	}

	question := &survey.MultiSelect{
		Message: message,
		Options: options,
	}

	if err := AskOne(question, choices, survey.Required); err != nil {
		// this should not error
		fmt.Println("error with input")
		return err
	}

	return nil
}

func ChooseBool(message string, target *bool) error {

	yes, no := "yes", "no"

	question := &survey.Select{
		Message: message,
		Options: []string{yes, no},
	}

	var choice string
	if err := AskOne(question, &choice, survey.Required); err != nil {
		return err
	}

	*target = choice == yes
	return nil
}

type JoinerData interface {
	Join() string
	ID() string
}
type JoinerDataSlice []JoinerData

func SelectJoinedData(message string, target *string, list []JoinerData) error {
	var optionsList []string
	for i, j := range list {
		// construct the options
		optionsList = append(optionsList, fmt.Sprintf("%v. %v", i, j.Join()))
	}
	question := &survey.Select{
		Message: message,
		Options: optionsList,
	}

	var choice string
	if err := AskOne(question, &choice, survey.Required); err != nil {
		return err
	}

	parts := strings.SplitN(choice, ".", 2)
	index, err := strconv.Atoi(parts[0])
	if err != nil {
		return err
	}

	*target = list[index].ID()

	return nil
}

func EnsureCsv(message string, source string, target *[]string, staticMode bool) error {
	if staticMode && source == "" {
		return fmt.Errorf(message)
	}
	if !staticMode {
		if err := GetStringInput(message, &source); err != nil {
			return err
		}
	}
	parts := strings.Split(source, ",")
	*target = parts
	return nil
}

// Expected format of source: k1,v1,k2,v2
func EnsureKVCsv(message string, source string, target *map[string]string, staticMode bool) error {
	parts := []string{}
	EnsureCsv(message, source, &parts, staticMode)
	if len(parts) == 1 && parts[0] == "" {
		// case where user does not specify any values
		return nil
	}
	if len(parts)%2 != 0 {
		return fmt.Errorf("Must provide one key per value (received an odd sum)")
	}
	for i := 0; i < len(parts)/2; i++ {
		(*target)[parts[i*2]] = parts[i*2+1]
	}
	return nil
}

repository: solo-io/gloo

license_type: permissive

repo_name: solo-io/gloo

branch_name: refs/heads/main

gha_language: Go

extension: go


text:
function(setVersionForTarget target)
  set_target_properties(${target}
    PROPERTIES
    VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}
    SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR}
  )
endfunction()

repository: wadesalazar/open-vds

repo_name: wadesalazar/open-vds

branch_name: refs/heads/master

extension: cmake


text:
package logging

import (
	"fmt"
	"github.com/sirupsen/logrus"
	"io"
	"os"
)

var Logger *logrus.Logger

func Setup(directory string, filename string, logLevel string, stdout bool) {
    // Create directory path if doesn't exist
	if _, err := os.Stat(directory); os.IsNotExist(err) {
		err = os.MkdirAll(directory, 0750)
		if err != nil {
			panic(fmt.Sprintf("Unable to to write to create [%s] directory for logging", directory))
		}
	}

	var level logrus.Level
	level = LogLevel(logLevel)
	logger := &logrus.Logger{
		Level: level,
		Formatter: &logrus.TextFormatter{
			DisableColors: true,
			FullTimestamp: true,
		},
	}
	// Output calling method on message
	logger.SetReportCaller(true)

	file, err := os.OpenFile(fmt.Sprintf("%s/%s", directory, filename),
		os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err == nil {
		if stdout {
			// Send to log file and standard out
			mw := io.MultiWriter(os.Stdout, file)
			logger.SetOutput(mw)
		} else {
			logger.SetOutput(file)
		}
	} else {
		panic(fmt.Sprintf("Failed to log to %s/%s, can not continue", directory, filename))
	}

	Logger = logger

	Logger.Info("Logger Initialized")
}

func LogLevel(lvl string) logrus.Level {
	switch lvl {
	case "debug":
		return logrus.DebugLevel
	case "info":
		return logrus.InfoLevel
	case "error":
		return logrus.ErrorLevel
	case "fatal":
		return logrus.FatalLevel
	default:
		panic("Log level not supported, verify settings for supported log level: [debug, info, error, fatal]")
	}
}

license: MIT

gha_license_id: MIT


text:
@Proceedings{FE-2015,
  booktitle = {Proceedings of the 1st International Workshop on Feature Extraction: Modern Questions and Challenges at NIPS 2015},
  conference_number = 1,
  name = {Feature Extraction: Modern Questions and Challenges},
  editor = {Dmitry Storcheus and Afshin Rostamizadeh and Sanjiv Kumar},
  start = {2015-12-11},
  end = {2015-12-11},
  published = {2015-12-08},
  address = {Montreal, Canada},
  volume = {44},
  year = {2015},
  shortname = {FE},
}

repository: mlresearch/papersite

repo_name: mlresearch/papersite

gha_language: TeX

extension: bib


text:
DESCRIPTION = "Tools i/o Package Group"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

inherit packagegroup

RDEPENDS_${PN} = " \
	i2c-tools \
    	devmem2 \
    	evtest \
    	spitools \
	rpmsg-tools \
    "

gha_language: BitBake

extension: bb


text:
package cache

import (
	"context"
	"github.com/go-redis/redis/v8"
	"iaas/internal/log"
	"time"
)

// RedisCache is a cache implementation which uses Redis as the backend.
type RedisCache struct {
	rdb *redis.Client
}

// NewRedisCache constructs a new RedisCache.
func NewRedisCache(addr, password string, db int) *RedisCache {
	rdb := redis.NewClient(&redis.Options{
		Addr:     addr,
		Password: password,
		DB:       db,
	})

	return &RedisCache{
		rdb: rdb,
	}
}

// Get fetches key from Redis.
func (r RedisCache) Get(key string) (cached interface{}, found bool) {
	val, err := r.rdb.Get(context.Background(), key).Result()
	if err != nil {
		return nil, false
	}

	if len(val) < 1 {
		return nil, false
	}

	return val, true
}

// Set sets data to Redis.
func (r RedisCache) Set(key string, value interface{}, expiration time.Duration) {
	err := r.rdb.Set(context.Background(), key, value, expiration).Err()
	if err != nil {
		log.Errorw("redis cache has failed to set",
			"error", err,
		)
	}
}


text:
require mender-artifact.inc

SRC_URI = "git://github.com/mendersoftware/mender-artifact.git;protocol=https;branch=2.2.x"

# Tag: 2.2.0b1
SRCREV = "00ee00c95db4f2dae0ec23a3165acde9ab34b2a7"

# Enable this in Betas, not in finals.
# Downprioritize this recipe in version selections.
DEFAULT_PREFERENCE = "-1"

LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://src/github.com/mendersoftware/mender-artifact/LIC_FILES_CHKSUM.sha256;md5=1baf9ba39aca12f99a87a99b18440e84"

repository: mirzak/meta-mender

repo_name: mirzak/meta-mender

gha_language: Python


text:
@article{chen2018trust,
 author = {Chen, Ling-Jiao and Gao, Jian},
 journal = {Physica A: Statistical Mechanics and its Applications},
 pages = {679--691},
 title = {A trust-based recommendation method using network diffusion processes},
 volume = {506},
 year = {2018}
}


text:
@inproceedings{KamathSU20,
 author = {Kamath, Gautam and Singhal, Vikrant and Ullman, Jonathan},
 booktitle = {Proceedings of the 33rd Annual Conference on Learning Theory},
 month = {July},
 series = {COLT '20},
 title = {Private Mean Estimation of Heavy-Tailed Distributions},
 url = {https://arxiv.org/abs/2002.09464},
 year = {2020}
}

repository: TheSalon/academic-kickstart

repo_name: TheSalon/academic-kickstart


text:
//go:generate go-bindata -pkg static -ignore static/static.gen.go -o static/static.gen.go static/...
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"sync"

	"github.com/wyattjoh/multi/cmd/multi-client/static"
)

func setupWebServer(addr string, api *API) error {

	wsh := &WebsocketHandler{
		API: api,
	}

	http.Handle("/ws", wsh)
	http.HandleFunc("/host", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, r.Host)
	})
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

		// Copy the index file to the response writer.
		buf := bytes.NewReader(static.MustAsset("static/index.html"))

		io.Copy(w, buf)
	})

	return http.ListenAndServe(addr, nil)
}

func main() {
	var addr = flag.String("addr", ":8080", "address for the http/websocket server")
	var apiaddr = flag.String("apiaddr", "127.0.0.1:7070", "address for the api server")

	flag.Parse()

	var wg sync.WaitGroup

	wg.Add(1)

	var api = NewAPI()

	go func() {

		// Setup the web server.
		if err := setupWebServer(*addr, api); err != nil {
			log.Printf("Failed to start web server: %s\n", err.Error())
		}

		// Finish the waitgroup.
		wg.Done()
	}()

	// Start up the api pump.
	if err := api.ListenAndServe(*apiaddr); err != nil {
		log.Printf("Failed to run API pump: %s\n", err.Error())
	}

	wg.Wait()
}

repository: wyattjoh/multi

repo_name: wyattjoh/multi


text:
// Code generated by go-swagger; DO NOT EDIT.

package backup

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"fmt"
	"io"

	"github.com/go-openapi/runtime"
	"github.com/go-openapi/strfmt"

	"mnimidamonbackend/models"
)

// UploadBackupReader is a Reader for the UploadBackup structure.
type UploadBackupReader struct {
	formats strfmt.Registry
}

// ReadResponse reads a server response into the received o.
func (o *UploadBackupReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
	switch response.Code() {
	case 200:
		result := NewUploadBackupOK()
		if err := result.readResponse(response, consumer, o.formats); err != nil {
			return nil, err
		}
		return result, nil
	case 400:
		result := NewUploadBackupBadRequest()
		if err := result.readResponse(response, consumer, o.formats); err != nil {
			return nil, err
		}
		return nil, result
	case 401:
		result := NewUploadBackupUnauthorized()
		if err := result.readResponse(response, consumer, o.formats); err != nil {
			return nil, err
		}
		return nil, result
	case 500:
		result := NewUploadBackupInternalServerError()
		if err := result.readResponse(response, consumer, o.formats); err != nil {
			return nil, err
		}
		return nil, result
	default:
		return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
	}
}

// NewUploadBackupOK creates a UploadBackupOK with default headers values
func NewUploadBackupOK() *UploadBackupOK {
	return &UploadBackupOK{}
}

/* UploadBackupOK describes a response with status code 200, with default header values.

The updated backup object.
*/
type UploadBackupOK struct {
	Payload *models.Backup
}

func (o *UploadBackupOK) Error() string {
	return fmt.Sprintf("[POST /users/current/computers/current/groups/{group_id}/backups/{backup_id}/upload][%d] uploadBackupOK  %+v", 200, o.Payload)
}
func (o *UploadBackupOK) GetPayload() *models.Backup {
	return o.Payload
}

func (o *UploadBackupOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

	o.Payload = new(models.Backup)

	// response payload
	if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
		return err
	}

	return nil
}

// NewUploadBackupBadRequest creates a UploadBackupBadRequest with default headers values
func NewUploadBackupBadRequest() *UploadBackupBadRequest {
	return &UploadBackupBadRequest{}
}

/* UploadBackupBadRequest describes a response with status code 400, with default header values.

Supplied parameters were not okay.
*/
type UploadBackupBadRequest struct {
	Payload *models.Error
}

func (o *UploadBackupBadRequest) Error() string {
	return fmt.Sprintf("[POST /users/current/computers/current/groups/{group_id}/backups/{backup_id}/upload][%d] uploadBackupBadRequest  %+v", 400, o.Payload)
}
func (o *UploadBackupBadRequest) GetPayload() *models.Error {
	return o.Payload
}

func (o *UploadBackupBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

	o.Payload = new(models.Error)

	// response payload
	if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
		return err
	}

	return nil
}

// NewUploadBackupUnauthorized creates a UploadBackupUnauthorized with default headers values
func NewUploadBackupUnauthorized() *UploadBackupUnauthorized {
	return &UploadBackupUnauthorized{}
}

/* UploadBackupUnauthorized describes a response with status code 401, with default header values.

Unauthorized.
*/
type UploadBackupUnauthorized struct {
	Payload *models.Error
}

func (o *UploadBackupUnauthorized) Error() string {
	return fmt.Sprintf("[POST /users/current/computers/current/groups/{group_id}/backups/{backup_id}/upload][%d] uploadBackupUnauthorized  %+v", 401, o.Payload)
}
func (o *UploadBackupUnauthorized) GetPayload() *models.Error {
	return o.Payload
}

func (o *UploadBackupUnauthorized) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

	o.Payload = new(models.Error)

	// response payload
	if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
		return err
	}

	return nil
}

// NewUploadBackupInternalServerError creates a UploadBackupInternalServerError with default headers values
func NewUploadBackupInternalServerError() *UploadBackupInternalServerError {
	return &UploadBackupInternalServerError{}
}

/* UploadBackupInternalServerError describes a response with status code 500, with default header values.

Internal server error.
*/
type UploadBackupInternalServerError struct {
	Payload *models.Error
}

func (o *UploadBackupInternalServerError) Error() string {
	return fmt.Sprintf("[POST /users/current/computers/current/groups/{group_id}/backups/{backup_id}/upload][%d] uploadBackupInternalServerError  %+v", 500, o.Payload)
}
func (o *UploadBackupInternalServerError) GetPayload() *models.Error {
	return o.Payload
}

func (o *UploadBackupInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

	o.Payload = new(models.Error)

	// response payload
	if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
		return err
	}

	return nil
}

repository: mnimidamon/mnimidamon-frontend

repo_name: mnimidamon/mnimidamon-frontend


text:
require coreutils-${PV}.inc
require coreutils-native.inc

PR = "r4"

SRC_URI[md5sum] = "c15219721e6590fa13bf50af49e712c2"
SRC_URI[sha256sum] = "efa27532ec6dc12a21f703ad4a0f612e613e9cc2575147685db81cc701952ac9"

repository: libo/openembedded

repo_name: libo/openembedded

branch_name: HEAD


text:
package madux_module

import (
	"os"

	"github.com/allmad/madux/madux_conn"
	"github.com/allmad/madux/madux_context"
)

var _ Handler = &Session{}

type SessionType int32

const (
	SessionTypePull SessionType = iota
	SessionTypePullResp
	SessionTypeList
	SessionTypeListResp
)

type SessionItem struct {
	Id       int32
	Name     string
	Attached bool
}

func (s *SessionItem) Marshal(b *madux_conn.Buffer) error {
	b.PutInt32(s.Id)
	b.PutString(s.Name)
	b.PutBool(s.Attached)
	return nil
}

func (s *SessionItem) Unmarshal(b *madux_conn.Buffer) error {
	s.Id = b.Int32()
	s.Name = b.String()
	s.Attached = b.Bool()
	return nil
}

type SessionList []*SessionItem

type Session struct {
	Id   int32
	Type SessionType

	Start  int32
	Output []byte
	List   []*SessionItem
}

func (s *Session) Marshal(b *madux_conn.Buffer) error {
	b.PutInt32(s.Id)
	b.PutInt32(int32(s.Type))
	b.PutInt32(s.Start)
	b.PutBytes(s.Output)
	b.PutInt32(int32(len(s.List)))
	for _, item := range s.List {
		b.PutMessage(item)
	}
	return nil
}

func (s *Session) Unmarshal(b *madux_conn.Buffer) error {
	s.Id = b.Int32()
	s.Type = SessionType(b.Int32())
	s.Start = b.Int32()
	s.Output = b.Bytes()
	listCnt := b.Int32()
	if listCnt > 0 {
		s.List = make([]*SessionItem, listCnt)
		for idx := range s.List {
			s.List[idx] = &SessionItem{}
			b.Message(s.List[idx])
		}
	}
	return nil
}

func (s *Session) HandleClient(ctx *madux_context.C) error {
	switch s.Type {
	case SessionTypeListResp:
	case SessionTypePullResp:
		ctx.Offset = s.Start
		os.Stdout.Write(s.Output)
	}
	return nil
}

func (s *Session) Handle(ctx *madux_context.T) error {
	switch s.Type {
	case SessionTypePull:
		sess := ctx.Sessions.GetById(s.Id)
		if sess == nil {
			return nil
		}
		if ctx.Conn.Width > 0 {
			sess.Pty.SetSize(ctx.Conn.Width, ctx.Conn.Height)
		}
		output, start := sess.GetOutput(int(s.Start))

		return ctx.Conn.SendMsg(&Session{
			Id:     s.Id,
			Type:   SessionTypePullResp,
			Start:  int32(start),
			Output: output,
		})
	case SessionTypeList:
		ret := make([]*SessionItem, len(ctx.Sessions.List()))
		for idx, sess := range ctx.Sessions.List() {
			ret[idx] = &SessionItem{
				Id:   sess.Id,
				Name: sess.Name,
			}
		}
		return ctx.Conn.SendMsg(&Session{
			Type: SessionTypeListResp,
			List: ret,
		})
	}
	return nil
}

repository: allmad/madux

repo_name: allmad/madux


text:
/*Copyright (c) 2018 The Paradox Game Converters Project
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.*/

#include "HoI4FocusTree.h"
#include "HoI4Country.h"
#include "HoI4Focus.h"
#include "HoI4Localisation.h"
#include "HoI4World.h"
#include "../Configuration.h"
#include "../V2World/Party.h"
#include "Log.h"
#include "OSCompatibilityLayer.h"
#include "ParserHelpers.h"
#include <fstream>
using namespace std;

//this is used to cache focuses that can be just loaded from a file
static std::map<std::string, HoI4Focus> loadedFocuses;

HoI4FocusTree::HoI4FocusTree(const HoI4Country& country) :
	srcCountryTag(country.getSourceCountry()->getTag()),
	dstCountryTag(country.getTag())
{
}

void HoI4FocusTree::addGenericFocusTree(const set<string>& majorIdeologies)
{
	confirmLoadedFocuses();

	shared_ptr<HoI4Focus> newFocus = make_shared<HoI4Focus>(loadedFocuses.find("army_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("equipment_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("motorization_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("doctrine_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("equipment_effort_2")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("mechanization_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("doctrine_effort_2")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("equipment_effort_3")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("armor_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("special_forces")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("aviation_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("fighter_focus")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("bomber_focus")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("aviation_effort_2")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("CAS_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("rocket_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("NAV_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("naval_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("flexible_navy")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("large_navy")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("submarine_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("cruiser_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("destroyer_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("capital_ships_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("industrial_effort")->second);
	newFocus->aiWillDo = "= {\n";
	newFocus->aiWillDo += "			factor = 3\n";
	newFocus->aiWillDo += "			modifier = {\n";
	newFocus->aiWillDo += "				factor = 0\n";
	newFocus->aiWillDo += "				date < 1939.1.1\n";
	newFocus->aiWillDo += "				OR = {\n";
	newFocus->aiWillDo += "					# we also dont want tiny nations to go crazy with slots right away\n";
	newFocus->aiWillDo += "					num_of_controlled_states < 2\n";
	newFocus->aiWillDo += "				}\n";
	newFocus->aiWillDo += "			}\n";
	newFocus->aiWillDo += "		}";
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("construction_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("production_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("construction_effort_2")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("production_effort_2")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("infrastructure_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("production_effort_3")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("infrastructure_effort_2")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("construction_effort_3")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("nuclear_effort")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("extra_tech_slot")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("extra_tech_slot_2")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("secret_weapons")->second);
	focuses.push_back(newFocus);

	int numCollectovistIdeologies = calculateNumCollectovistIdeologies(majorIdeologies);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("political_effort")->second);
	newFocus->xPos = static_cast<int>((numCollectovistIdeologies * 1.5) + 16);
	focuses.push_back(newFocus);

	if (numCollectovistIdeologies > 0)
	{
		newFocus = make_shared<HoI4Focus>(loadedFocuses.find("collectivist_ethos")->second);
		newFocus->available = "= {\n";
		newFocus->available += "			OR = {\n";
		for (auto majorIdeology : majorIdeologies)
		{
			if (majorIdeology == "democratic")
			{
				continue;
			}
			newFocus->available += "				has_government = " + majorIdeology + "\n";
		}
		newFocus->available += "			}\n";
		newFocus->available += "		}";
		newFocus->xPos = -(numCollectovistIdeologies / 2) - 1;
		newFocus->completionReward = "= {\n";
		if (majorIdeologies.count("democratic") > 0)
		{
			newFocus->completionReward += "			add_ideas = collectivist_ethos_focus_democratic\n";
		}
		else
		{
			newFocus->completionReward += "			add_ideas = collectivist_ethos_focus_neutral\n";
		}
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);

		determineMutualExclusions(majorIdeologies);

		string ideolgicalFanaticsmPrereqs;
		int relativePosition = 1 - numCollectovistIdeologies;
		if (majorIdeologies.count("fascism") > 0)
		{
			addFascistGenericFocuses(relativePosition, majorIdeologies);
			if (ideolgicalFanaticsmPrereqs.size() > 0)
			{
				ideolgicalFanaticsmPrereqs += " ";
			}
			ideolgicalFanaticsmPrereqs += "focus = paramilitarism";
			relativePosition += 2;
		}
		if (majorIdeologies.count("communism") > 0)
		{
			addCommunistGenericFocuses(relativePosition);
			if (ideolgicalFanaticsmPrereqs.size() > 0)
			{
				ideolgicalFanaticsmPrereqs += " ";
			}
			ideolgicalFanaticsmPrereqs += "focus = political_commissars";
			relativePosition += 2;
		}
		if (majorIdeologies.count("absolutist") > 0)
		{
			addAbsolutistGenericFocuses(relativePosition);
			if (ideolgicalFanaticsmPrereqs.size() > 0)
			{
				ideolgicalFanaticsmPrereqs += " ";
			}
			ideolgicalFanaticsmPrereqs += "focus = historical_claims_focus";
			relativePosition += 2;
		}
		if (majorIdeologies.count("radical") > 0)
		{
			addRadicalGenericFocuses(relativePosition);
			if (ideolgicalFanaticsmPrereqs.size() > 0)
			{
				ideolgicalFanaticsmPrereqs += " ";
			}
			ideolgicalFanaticsmPrereqs += "focus = army_provides_focus";
		}

		newFocus = make_shared<HoI4Focus>(loadedFocuses.find("ideological_fanaticism")->second);
		newFocus->prerequisites.clear();
		newFocus->prerequisites.push_back("= { " + ideolgicalFanaticsmPrereqs + " }");
		newFocus->xPos = 0;
		newFocus->yPos = 6;
		newFocus->relativePositionId = "collectivist_ethos";
		focuses.push_back(newFocus);
	}

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("liberty_ethos")->second);
	if (numCollectovistIdeologies == 0)
	{
		newFocus->mutuallyExclusive.clear();
	}
	if (majorIdeologies.count("democratic") == 0)
	{
		newFocus->available = "= {\n";
		newFocus->available += "			has_government = neutrality\n";
		newFocus->available += "		}";
	}
	newFocus->xPos = (numCollectovistIdeologies + 1) / 2;
	newFocus->aiWillDo = "= {\n";
	newFocus->aiWillDo += "			factor = 95\n";
	newFocus->aiWillDo += "			modifier = {\n";
	newFocus->aiWillDo += "				factor = 0.1\n";
	newFocus->aiWillDo += "				any_neighbor_country = {\n";
	newFocus->aiWillDo += "					is_major = yes\n";
	newFocus->aiWillDo += "					OR = {\n";
	for (auto majorIdeology : majorIdeologies)
	{
		newFocus->aiWillDo += "						has_government = " + majorIdeology + "\n";
	}
	newFocus->aiWillDo += "					}\n";
	newFocus->aiWillDo += "				}\n";
	if (majorIdeologies.count("democratic") > 0)
	{
		newFocus->aiWillDo += "				NOT = {\n";
		newFocus->aiWillDo += "					any_neighbor_country = {\n";
		newFocus->aiWillDo += "						is_major = yes\n";
		newFocus->aiWillDo += "						has_government = democratic\n";
		newFocus->aiWillDo += "					}\n";
		newFocus->aiWillDo += "				}\n";
	}
	newFocus->aiWillDo += "			}\n";
	newFocus->aiWillDo += "		}";
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("neutrality_focus")->second);
	if (majorIdeologies.count("democratic") == 0)
	{
		newFocus->mutuallyExclusive.clear();
	}
	newFocus->aiWillDo = "= {\n";
	newFocus->aiWillDo += "			factor = 1\n";
	newFocus->aiWillDo += "		}";
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("deterrence")->second);
	focuses.push_back(newFocus);

	if (majorIdeologies.count("democratic") != 0)
	{
		newFocus = make_shared<HoI4Focus>(loadedFocuses.find("interventionism_focus")->second);
		focuses.push_back(newFocus);

		newFocus = make_shared<HoI4Focus>(loadedFocuses.find("volunteer_corps")->second);
		focuses.push_back(newFocus);

		newFocus = make_shared<HoI4Focus>(loadedFocuses.find("foreign_expeditions")->second);
		focuses.push_back(newFocus);
	}

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("why_we_fight")->second);
	if (majorIdeologies.count("democratic") == 0)
	{
		newFocus->prerequisites.clear();
		newFocus->prerequisites.push_back("= { focus = deterrence }");
	}
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("technology_sharing")->second);
	if (numCollectovistIdeologies == 0)
	{
		newFocus->prerequisites.clear();
		newFocus->prerequisites.push_back("= { focus = why_we_fight }");
	}
	newFocus->xPos = numCollectovistIdeologies;
	focuses.push_back(newFocus);

	nextFreeColumn = static_cast<int>(numCollectovistIdeologies * 1.5) + ((numCollectovistIdeologies + 1) / 2) + 20;
}

void HoI4FocusTree::confirmLoadedFocuses()
{
	if (loadedFocuses.size() == 0)
	{
		registerKeyword(std::regex("focus_tree"), [this](const std::string& unused, std::istream& theStream) {});
		registerKeyword(std::regex("id"), commonItems::ignoreString);
		registerKeyword(std::regex("country"), commonItems::ignoreObject);
		registerKeyword(std::regex("default"), commonItems::ignoreString);
		registerKeyword(std::regex("reset_on_civilwar"), commonItems::ignoreString);
		registerKeyword(std::regex("focus"), [this](const std::string& unused, std::istream& theStream)
		{
			HoI4Focus newFocus(theStream);
			loadedFocuses.insert(make_pair(newFocus.id, newFocus));
		}
		);

		parseFile(theConfiguration.getHoI4Path() + "/common/national_focus/generic.txt");
		parseFile("converterFocuses.txt");
	}
}

int HoI4FocusTree::calculateNumCollectovistIdeologies(const set<string>& majorIdeologies)
{
	int numCollectovistIdeologies = 0;
	numCollectovistIdeologies += majorIdeologies.count("radical");
	numCollectovistIdeologies += majorIdeologies.count("absolutist");
	numCollectovistIdeologies += majorIdeologies.count("communism");
	numCollectovistIdeologies += majorIdeologies.count("fascism");
	return numCollectovistIdeologies;
}

void HoI4FocusTree::determineMutualExclusions(const set<string>& majorIdeologies)
{
	if (majorIdeologies.count("fascism") > 0)
	{
		communistMutualExclusions += "focus = nationalism_focus";
		absolutistMutualExlusions += "focus = nationalism_focus";
		radicalMutualExclusions += "focus = nationalism_focus";
	}
	if (majorIdeologies.count("communism") > 0)
	{
		if (fascistMutualExlusions.size() > 0)
		{
			fascistMutualExlusions += " ";
		}
		if (absolutistMutualExlusions.size() > 0)
		{
			absolutistMutualExlusions += " ";
		}
		if (radicalMutualExclusions.size() > 0)
		{
			radicalMutualExclusions += " ";
		}
		fascistMutualExlusions += "focus = internationalism_focus";
		absolutistMutualExlusions += "focus = internationalism_focus";
		radicalMutualExclusions += "focus = internationalism_focus";
	}
	if (majorIdeologies.count("absolutist") > 0)
	{
		if (fascistMutualExlusions.size() > 0)
		{
			fascistMutualExlusions += " ";
		}
		if (communistMutualExclusions.size() > 0)
		{
			communistMutualExclusions += " ";
		}
		if (radicalMutualExclusions.size() > 0)
		{
			radicalMutualExclusions += " ";
		}
		fascistMutualExlusions += "focus = absolutism_focus";
		communistMutualExclusions += "focus = absolutism_focus";
		radicalMutualExclusions += "focus = absolutism_focus";
	}
	if (majorIdeologies.count("radical") > 0)
	{
		if (fascistMutualExlusions.size() > 0)
		{
			fascistMutualExlusions += " ";
		}
		if (communistMutualExclusions.size() > 0)
		{
			communistMutualExclusions += " ";
		}
		if (absolutistMutualExlusions.size() > 0)
		{
			absolutistMutualExlusions += " ";
		}
		fascistMutualExlusions += "focus = radical_focus";
		communistMutualExclusions += "focus = radical_focus";
		absolutistMutualExlusions += "focus = radical_focus";
	}
}

void HoI4FocusTree::addFascistGenericFocuses(int relativePosition, const std::set<std::string>& majorIdeologies)
{
	shared_ptr<HoI4Focus> newFocus = make_shared<HoI4Focus>(loadedFocuses.find("nationalism_focus")->second);
	newFocus->mutuallyExclusive = "= { " + fascistMutualExlusions + " }";
	newFocus->xPos = relativePosition;
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("militarism")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("military_youth")->second);
	newFocus->completionReward = "= {\n";
	newFocus->completionReward += "			add_ideas = military_youth_focus\n";
	for (auto ideology : majorIdeologies)
	{
		newFocus->completionReward += "			if = {\n";
		newFocus->completionReward += "				limit = { has_government = " + ideology + " }\n";
		newFocus->completionReward += "				add_popularity = {\n";
		newFocus->completionReward += "					ideology = " + ideology + "\n";
		newFocus->completionReward += "					popularity = 0.2\n";
		newFocus->completionReward += "				}\n";
		newFocus->completionReward += "			}\n";
	}
	newFocus->completionReward += "		}";
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("paramilitarism")->second);
	focuses.push_back(newFocus);
}

void HoI4FocusTree::addCommunistGenericFocuses(int relativePosition)
{
	shared_ptr<HoI4Focus> newFocus = make_shared<HoI4Focus>(loadedFocuses.find("internationalism_focus")->second);
	newFocus->mutuallyExclusive = "= { " + communistMutualExclusions + " }";
	newFocus->available = "= {\n";
	newFocus->available += "			OR = {\n";
	newFocus->available += "				has_government = communism\n";
	newFocus->available += "				has_government = neutrality\n";
	newFocus->available += "			}\n";
	newFocus->available += "		}";
	newFocus->xPos = relativePosition;
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("political_correctness")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("indoctrination_focus")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("political_commissars")->second);
	newFocus->completionReward = "= {\n";
	newFocus->completionReward += "			add_ideas = political_commissars_focus\n";
	newFocus->completionReward += "			if = {\n";
	newFocus->completionReward += "				limit = { has_government = communism }\n";
	newFocus->completionReward += "				add_popularity = {\n";
	newFocus->completionReward += "					ideology = communism\n";
	newFocus->completionReward += "					popularity = 0.2\n";
	newFocus->completionReward += "				}\n";
	newFocus->completionReward += "			}\n";
	newFocus->completionReward += "			add_political_power = 200\n";
	newFocus->completionReward += "		}";
	focuses.push_back(newFocus);
}

void HoI4FocusTree::addAbsolutistGenericFocuses(int relativePosition)
{
	shared_ptr<HoI4Focus> newFocus = make_shared<HoI4Focus>(loadedFocuses.find("absolutism_focus")->second);
	newFocus->mutuallyExclusive = "= { " + absolutistMutualExlusions + " }";
	newFocus->xPos = relativePosition;
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("royal_dictatorship_focus")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("royal_army_tradition_focus")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("historical_claims_focus")->second);
	focuses.push_back(newFocus);
}

void HoI4FocusTree::addRadicalGenericFocuses(int relativePosition)
{
	shared_ptr<HoI4Focus> newFocus = make_shared<HoI4Focus>(loadedFocuses.find("radical_focus")->second);
	newFocus->mutuallyExclusive = "= { " + radicalMutualExclusions + " }";
	newFocus->xPos = relativePosition;
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("private_channels_focus")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("hardfought_market_focus")->second);
	focuses.push_back(newFocus);

	newFocus = make_shared<HoI4Focus>(loadedFocuses.find("army_provides_focus")->second);
	focuses.push_back(newFocus);
}

shared_ptr<HoI4FocusTree> HoI4FocusTree::makeCustomizedCopy(const HoI4Country& country) const
{
	auto newFocusTree = make_shared<HoI4FocusTree>(country);

	for (auto focus : focuses)
	{
		auto newFocus = focus->makeCustomizedCopy(newFocusTree->dstCountryTag);
		newFocusTree->addFocus(newFocus);
	}
	newFocusTree->setNextFreeColumn(nextFreeColumn);

	return newFocusTree;
}

void HoI4FocusTree::addDemocracyNationalFocuses(shared_ptr<HoI4Country> Home, vector<shared_ptr<HoI4Country>>& CountriesToContain)
{
	double WTModifier = 1;
	if (Home->getGovernmentIdeology() == "democratic")
	{
		string warPol = Home->getRulingParty().getWarPolicy();
		if (warPol == "jingoism")
		{
			WTModifier = 0;
		}
		if (warPol == "pro_military")
		{
			WTModifier = 0.25;
		}
		if (warPol == "anti_military")
		{
			WTModifier = 0.5;
		}
		if (warPol == "pacifism" || warPol == "pacifist")
		{
			WTModifier = 0.5;
		}
	}

	shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("WarProp")->second.makeCustomizedCopy(Home->getTag());
	newFocus->available = "= {\n";
	newFocus->available += "			threat > " + to_string(0.20 * WTModifier / 1000) + "\n";
	newFocus->available += "		}";
	newFocus->xPos = nextFreeColumn + (CountriesToContain.size() * 2) - 1;
	focuses.push_back(newFocus);

	newFocus = loadedFocuses.find("PrepInter")->second.makeCustomizedCopy(Home->getTag());
	newFocus->available = "= {\n";
	newFocus->available += "			threat > " + to_string(0.30 * WTModifier / 1000) + "\n";
	newFocus->available += "		}";
	focuses.push_back(newFocus);

	newFocus = loadedFocuses.find("Lim")->second.makeCustomizedCopy(Home->getTag());
	newFocus->available = "= {\n";
	newFocus->available += "			threat > " + to_string(0.50 * WTModifier / 1000) + "\n";
	newFocus->available += "		}";
	focuses.push_back(newFocus);

	int relavtivePos = 1 - (CountriesToContain.size() * 2);
	for (auto country : CountriesToContain)
	{
		auto possibleContainedCountryName = country->getSourceCountry()->getName("english");
		string containedCountryName;
		if (possibleContainedCountryName)
		{
			containedCountryName = *possibleContainedCountryName;
		}
		else
		{
			LOG(LogLevel::Warning) << "Could not determine contained country name for democratic focuses";
			containedCountryName = "";
		}

		newFocus = loadedFocuses.find("WarPlan")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id += country->getTag();
		newFocus->text = "War Plan " + containedCountryName;
		newFocus->bypass = "= {\n";
		newFocus->bypass += "			has_war_with = " + country->getTag() + "\n";
		newFocus->bypass += "		}";
		newFocus->xPos = relavtivePos;
		newFocus->available = "= {\n";
		newFocus->available += "			any_other_country = {\n";
		newFocus->available += "				original_tag = " + country->getTag() + "\n";
		newFocus->available += "				exists = yes\n";
		newFocus->available += "				NOT = { has_government = democratic } \n";
		newFocus->available += "				NOT = { is_in_faction_with = " + Home->getTag() + " }\n";
		newFocus->available += "				OR = {\n";
		newFocus->available += "					has_offensive_war = yes\n";
		newFocus->available += "					has_added_tension_amount > 30\n";
		newFocus->available += "				}\n";
		newFocus->available += "			}\n";
		newFocus->available += "		}";
		focuses.push_back(newFocus);
		HoI4Localisation::copyFocusLocalisations("WarPlan", newFocus->id);
		HoI4Localisation::updateLocalisationWithCountry(newFocus->id, "$TARGET", country->getTag() + "_neutrality");

		newFocus = loadedFocuses.find("Embargo")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id += country->getTag();
		newFocus->text = "Embargo " + containedCountryName;
		newFocus->prerequisites.clear();
		newFocus->prerequisites.push_back("= { focus =  WarPlan" + Home->getTag() + country->getTag() + " }");
		newFocus->bypass = "= {\n";
		newFocus->bypass += "			has_war_with = " + country->getTag() + "\n";
		newFocus->bypass += "		}";
		newFocus->relativePositionId += country->getTag();
		newFocus->available = "= {\n";
		newFocus->available += "			any_other_country = {\n";
		newFocus->available += "				original_tag = " + country->getTag() + "\n";
		newFocus->available += "				exists = yes\n";
		newFocus->available += "				NOT = { has_government = democratic } \n";
		newFocus->available += "				NOT = { is_in_faction_with = " + Home->getTag() + " }\n";
		newFocus->available += "				OR = {\n";
		newFocus->available += "					has_offensive_war = yes\n";
		newFocus->available += "					has_added_tension_amount > 30\n";
		newFocus->available += "					threat > 0.6\n";
		newFocus->available += "				}\n";
		newFocus->available += "			}\n";
		newFocus->available += "		}";
		newFocus->completionReward = "= {\n";
		newFocus->completionReward += "			" + country->getTag() + " = {\n";
		newFocus->completionReward += "				add_opinion_modifier = { target = " + Home->getTag() + " modifier = embargo }\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
		HoI4Localisation::copyFocusLocalisations("Embargo", newFocus->id);
		HoI4Localisation::updateLocalisationWithCountry(newFocus->id, "$TARGET", country->getTag() + "_neutrality");

		newFocus = loadedFocuses.find("WAR")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id += country->getTag();
		newFocus->text = "Enact War Plan " + containedCountryName;
		newFocus->prerequisites.clear();
		newFocus->prerequisites.push_back("= { focus =  Embargo" + Home->getTag() + country->getTag() + " }");
		newFocus->prerequisites.push_back("= { focus =  Lim" + Home->getTag() + " }");
		newFocus->bypass = "= {\n";
		newFocus->bypass += "			has_war_with = " + country->getTag() + "\n";
		newFocus->bypass += "		}";
		newFocus->relativePositionId += country->getTag();
		newFocus->available = "= {\n";
		newFocus->available += "			has_war = no\n";
		newFocus->available += "			any_other_country = {\n";
		newFocus->available += "				original_tag = " + country->getTag() + "\n";
		newFocus->available += "				exists = yes\n";
		newFocus->available += "				NOT = { has_government = democratic } \n";
		newFocus->available += "				NOT = { is_in_faction_with = " + Home->getTag() + " }\n";
		newFocus->available += "				OR = {\n";
		newFocus->available += "					has_offensive_war = yes\n";
		newFocus->available += "					has_added_tension_amount > 30\n";
		newFocus->available += "					threat > 0.6\n";
		newFocus->available += "				}\n";
		newFocus->available += "			}\n";
		newFocus->available += "		}";
		newFocus->aiWillDo = "= {\n";
		newFocus->aiWillDo += "			factor = 10\n";
		newFocus->aiWillDo += "		}";
		newFocus->completionReward = "= {\n";
		newFocus->completionReward += "			declare_war_on = {\n";
		newFocus->completionReward += "				type = puppet_wargoal_focus\n";
		newFocus->completionReward += "				target = " + country->getTag() + "\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
		HoI4Localisation::copyFocusLocalisations("WAR", newFocus->id);
		HoI4Localisation::updateLocalisationWithCountry(newFocus->id, "$TARGET", country->getTag() + "_neutrality");

		relavtivePos += 4;
	}
}

void HoI4FocusTree::addAbsolutistEmpireNationalFocuses(shared_ptr<HoI4Country> Home, const vector<shared_ptr<HoI4Country>>& targetColonies, const vector<shared_ptr<HoI4Country>>& annexationTargets)
{
	auto possibleHomeCountryAdjective = Home->getSourceCountry()->getAdjective("english");
	string homeCountryAdjective;
	if (possibleHomeCountryAdjective)
	{
		homeCountryAdjective = *possibleHomeCountryAdjective;
	}
	else
	{
		LOG(LogLevel::Warning) << "Could not determine home country adjective for absolutist focuses";
		homeCountryAdjective = "";
	}

	auto newFocus = loadedFocuses.find("EmpireGlory")->second.makeCustomizedCopy(Home->getTag());
	newFocus->xPos = nextFreeColumn + 5;
	newFocus->yPos = 0;
	focuses.push_back(newFocus);

	newFocus = loadedFocuses.find("StrengthenColonies")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "EmpireGlory" + Home->getTag();
	newFocus->xPos = -1;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	newFocus = loadedFocuses.find("StrengthenHome")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "EmpireGlory" + Home->getTag();
	newFocus->xPos = 1;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	newFocus = loadedFocuses.find("ColonialInd")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "StrengthenColonies" + Home->getTag();
	newFocus->xPos = -2;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	newFocus = loadedFocuses.find("ColonialHwy")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "ColonialInd" + Home->getTag();
	newFocus->xPos = -2;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	newFocus = loadedFocuses.find("ResourceFac")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "ColonialInd" + Home->getTag();
	newFocus->xPos = 0;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	//establish colonial army
	newFocus = loadedFocuses.find("ColonialArmy")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "StrengthenColonies" + Home->getTag();
	newFocus->xPos = 0;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	//establish protectorate
	if (targetColonies.size() >= 1)
	{
		auto target = targetColonies.front();

		auto possibleProtectorateCountryName = target->getSourceCountry()->getName("english");
		string protectorateCountryName;
		if (possibleProtectorateCountryName)
		{
			protectorateCountryName = *possibleProtectorateCountryName;
		}
		else
		{
			LOG(LogLevel::Warning) << "Could not determine protectorate country name for absolutist focuses";
			protectorateCountryName = "";
		}

		newFocus = loadedFocuses.find("Protectorate")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id = "Protectorate" + Home->getTag() + target->getTag();
		newFocus->text += "Establish Protectorate over " + protectorateCountryName;
		newFocus->available += "= {\n";
		newFocus->available += "			" + target->getTag() + " = { is_in_faction = no }\n";
		newFocus->available += "		}";
		newFocus->prerequisites.push_back("= { focus = ColonialArmy" + Home->getTag() + " }");
		newFocus->relativePositionId = "ColonialArmy" + Home->getTag();
		newFocus->xPos = 0;
		newFocus->yPos = 1;
		newFocus->bypass += "= {\n";
		newFocus->bypass += "			OR = {\n";
		newFocus->bypass += "				" + Home->getTag() + " = {\n";
		newFocus->bypass += "					is_in_faction_with = " + target->getTag() + "\n";
		newFocus->bypass += "					has_war_with = " + target->getTag() + "\n";
		newFocus->bypass += "				}\n";
		newFocus->bypass += "				NOT = { country_exists = " + target->getTag() + " }\n";
		newFocus->bypass += "			}\n";
		newFocus->bypass += "		}";
		newFocus->aiWillDo += "= {\n";
		newFocus->aiWillDo += "			factor = 10\n";
		newFocus->aiWillDo += "			modifier = {\n";
		newFocus->aiWillDo += "				factor = 0\n";
		newFocus->aiWillDo += "				strength_ratio = { tag = " + target->getTag() + " ratio < 1 }\n";
		newFocus->aiWillDo += "			}\n";
		newFocus->aiWillDo += "		}";
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			create_wargoal = {\n";
		newFocus->completionReward += "				type = annex_everything\n";
		newFocus->completionReward += "				target = " + target->getTag() + "\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
	}
	if (targetColonies.size() >= 2)
	{
		auto target = targetColonies.back();

		auto possibleProtectorateCountryName = target->getSourceCountry()->getName("english");
		string protectorateCountryName;
		if (possibleProtectorateCountryName)
		{
			protectorateCountryName = *possibleProtectorateCountryName;
		}
		else
		{
			LOG(LogLevel::Warning) << "Could not determine protectorate country name for absolutist focuses";
			protectorateCountryName = "";
		}

		newFocus = loadedFocuses.find("Protectorate")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id = "Protectorate" + Home->getTag() + target->getTag();
		newFocus->text += "Establish Protectorate over " + protectorateCountryName;
		newFocus->available += "= {\n";
		newFocus->available += "			" + target->getTag() + " = { is_in_faction = no }\n";
		newFocus->available += "		}";
		newFocus->prerequisites.push_back("= { focus = Protectorate" + Home->getTag() + targetColonies.front()->getTag() + " }");
		newFocus->relativePositionId = "Protectorate" + Home->getTag() + targetColonies.front()->getTag();
		newFocus->xPos = 0;
		newFocus->yPos = 1;
		newFocus->bypass += "= {\n";
		newFocus->bypass += "			OR = {\n";
		newFocus->bypass += "				" + Home->getTag() + " = {\n";
		newFocus->bypass += "					is_in_faction_with = " + target->getTag() + "\n";
		newFocus->bypass += "					has_war_with = " + target->getTag() + "\n";
		newFocus->bypass += "				}\n";
		newFocus->bypass += "				NOT = { country_exists = " + target->getTag() + " }\n";
		newFocus->bypass += "			}\n";
		newFocus->bypass += "		}";
		newFocus->aiWillDo += "= {\n";
		newFocus->aiWillDo += "			factor = 5\n";
		newFocus->aiWillDo += "			modifier = {\n";
		newFocus->aiWillDo += "				factor = 0\n";
		newFocus->aiWillDo += "				strength_ratio = { tag = " + target->getTag() + " ratio < 1 }\n";
		newFocus->aiWillDo += "			}\n";
		newFocus->aiWillDo += "		}";
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			create_wargoal = {\n";
		newFocus->completionReward += "				type = annex_everything\n";
		newFocus->completionReward += "				target = " + target->getTag() + "\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
	}

	//Trade Empire
	newFocus = loadedFocuses.find("TradeEmpire")->second.makeCustomizedCopy(Home->getTag());
	newFocus->text += "Fund the " + homeCountryAdjective + " Colonial Trade Corporation";
	newFocus->relativePositionId = "ColonialInd" + Home->getTag();
	newFocus->xPos = -1;
	newFocus->yPos = 2;
	focuses.push_back(newFocus);

	//Home Industry Buildup
	newFocus = loadedFocuses.find("IndHome")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "StrengthenHome" + Home->getTag();
	newFocus->xPos = 1;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	//National Highway
	newFocus = loadedFocuses.find("NationalHwy")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "IndHome" + Home->getTag();
	newFocus->xPos = -1;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	//National College
	newFocus = loadedFocuses.find("NatCollege")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "IndHome" + Home->getTag();
	newFocus->xPos = 1;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	//Improve Factories
	newFocus = loadedFocuses.find("MilitaryBuildup")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "IndHome" + Home->getTag();
	newFocus->xPos = 2;
	newFocus->yPos = 2;
	focuses.push_back(newFocus);

	//PrepBorder
	newFocus = loadedFocuses.find("PrepTheBorder")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "StrengthenHome" + Home->getTag();
	newFocus->xPos = 4;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	//Promote Nationalistic Spirit
	newFocus = loadedFocuses.find("NatSpirit")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "PrepTheBorder" + Home->getTag();
	newFocus->xPos = 0;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	//ANNEX
	if (annexationTargets.size() >= 1)
	{
		auto target = annexationTargets.front();

		auto possibleTargetCountryName = target->getSourceCountry()->getName("english");
		string targetCountryName;
		if (possibleTargetCountryName)
		{
			targetCountryName = *possibleTargetCountryName;
		}
		else
		{
			LOG(LogLevel::Warning) << "Could not determine target country name for absolutist focuses";
			targetCountryName = "";
		}

		newFocus = loadedFocuses.find("Annex")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id = "Annex" + Home->getTag() + target->getTag();
		newFocus->text += "Conquer " + targetCountryName;
		newFocus->available += "= {\n";
		newFocus->available += "			" + target->getTag() + " = { is_in_faction = no }\n";
		newFocus->available += "		}";
		newFocus->prerequisites.push_back("= { focus = PrepTheBorder" + Home->getTag() + " }");
		newFocus->relativePositionId = "PrepTheBorder" + Home->getTag();
		newFocus->xPos = 2;
		newFocus->yPos = 1;
		newFocus->bypass += "= {\n";
		newFocus->bypass += "			OR = {\n";
		newFocus->bypass += "				" + Home->getTag() + "= {\n";
		newFocus->bypass += "					is_in_faction_with = " + target->getTag() + "\n";
		newFocus->bypass += "					has_war_with = " + target->getTag() + "\n";
		newFocus->bypass += "				}\n";
		newFocus->bypass += "				NOT = { country_exists = " + target->getTag() + " }\n";
		newFocus->bypass += "			}\n";
		newFocus->bypass += "		}";
		newFocus->aiWillDo += "= {\n";
		newFocus->aiWillDo += "			factor = 5\n";
		newFocus->aiWillDo += "			modifier = {\n";
		newFocus->aiWillDo += "				factor = 0\n";
		newFocus->aiWillDo += "				strength_ratio = { tag = " + target->getTag() + " ratio < 1 }\n";
		newFocus->aiWillDo += "			}\n";
		newFocus->aiWillDo += "		}";
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			create_wargoal = {\n";
		newFocus->completionReward += "				type = annex_everything\n";
		newFocus->completionReward += "				target = " + target->getTag() + "\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
	}
	if (annexationTargets.size() >= 2)
	{
		auto target = annexationTargets.back();

		auto possibleTargetCountryName = target->getSourceCountry()->getName("english");
		string targetCountryName;
		if (possibleTargetCountryName)
		{
			targetCountryName = *possibleTargetCountryName;
		}
		else
		{
			LOG(LogLevel::Warning) << "Could not determine target country name for absolutist focuses";
			targetCountryName = "";
		}

		newFocus = loadedFocuses.find("Annex")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id = "Annex" + Home->getTag() + target->getTag();
		newFocus->text += "Conquer " + targetCountryName;
		newFocus->available += "= {\n";
		newFocus->available += "			\"" + target->getTag() + "\" = { is_in_faction = no }\n";
		newFocus->available += "		}";
		newFocus->prerequisites.push_back("= { focus = NatSpirit" + Home->getTag() + " }");
		newFocus->relativePositionId = "NatSpirit" + Home->getTag();
		newFocus->xPos = 1;
		newFocus->yPos = 1;
		newFocus->bypass += "= {\n";
		newFocus->bypass += "			OR = {\n";
		newFocus->bypass += "				" + Home->getTag() + " = {\n";
		newFocus->bypass += "					is_in_faction_with = " + target->getTag() + "\n";
		newFocus->bypass += "					has_war_with = " + target->getTag() + "\n";
		newFocus->bypass += "				}\n";
		newFocus->bypass += "				NOT = { country_exists = " + target->getTag() + " }\n";
		newFocus->bypass += "			}\n";
		newFocus->bypass += "		}";
		newFocus->aiWillDo += "= {\n";
		newFocus->aiWillDo += "			factor = 5\n";
		newFocus->aiWillDo += "			modifier = {\n";
		newFocus->aiWillDo += "				factor = 0\n";
		newFocus->aiWillDo += "				strength_ratio = { tag = " + target->getTag() + " ratio < 1 }\n";
		newFocus->aiWillDo += "			}\n";
		newFocus->aiWillDo += "		}";
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			create_wargoal = {\n";
		newFocus->completionReward += "				type = annex_everything\n";
		newFocus->completionReward += "				target = " + target->getTag() + "\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
	}
}

void HoI4FocusTree::addCommunistCoupBranch(shared_ptr<HoI4Country> Home, const vector<shared_ptr<HoI4Country>>& coupTargets, const std::set<std::string>& majorIdeologies)
{
	if (coupTargets.size() > 0)
	{
		//Focus to increase Comm support and prereq for coupTargets
		shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("Home_of_Revolution")->second.makeCustomizedCopy(Home->getTag());
		newFocus->xPos = nextFreeColumn + coupTargets.size() - 1;
		newFocus->yPos = 0;
		focuses.push_back(newFocus);

		for (unsigned int i = 0; i < 2; i++)
		{
			if (i < coupTargets.size())
			{
				auto possibleCoupCountryName = coupTargets[i]->getSourceCountry()->getName("english");
				string coupCountryName;
				if (possibleCoupCountryName)
				{
					coupCountryName = *possibleCoupCountryName;
				}
				else
				{
					LOG(LogLevel::Warning) << "Could not determine coup country name for communist coup focuses";
					coupCountryName = "";
				}

				newFocus = loadedFocuses.find("Influence_")->second.makeCustomizedCopy(Home->getTag());
				newFocus->id = "Influence_" + coupTargets[i]->getTag() + "_" + Home->getTag();
				newFocus->text = "Influence " + coupCountryName;
				newFocus->xPos = nextFreeColumn + i * 2;
				newFocus->yPos = 1;
				newFocus->completionReward += "= {\n";
				newFocus->completionReward += "			" + coupTargets[i]->getTag() + " = {\n";
				if (majorIdeologies.count("fascism") > 0)
				{
					newFocus->completionReward += "				if = {\n";
					newFocus->completionReward += "					limit = {\n";
					newFocus->completionReward += "						" + Home->getTag() + " = {\n";
					newFocus->completionReward += "							has_government = fascism\n";
					newFocus->completionReward += "						}\n";
					newFocus->completionReward += "					}\n";
					newFocus->completionReward += "					add_ideas = fascist_influence\n";
					newFocus->completionReward += "				}\n";
				}
				if (majorIdeologies.count("communism") > 0)
				{
					newFocus->completionReward += "				if = {\n";
					newFocus->completionReward += "					limit = {\n";
					newFocus->completionReward += "						" + Home->getTag() + " = {\n";
					newFocus->completionReward += "							has_government = communism\n";
					newFocus->completionReward += "						}\n";
					newFocus->completionReward += "					}\n";
					newFocus->completionReward += "					add_ideas = communist_influence\n";
					newFocus->completionReward += "				}\n";
				}
				if (majorIdeologies.count("democratic") > 0)
				{
					newFocus->completionReward += "				if = {\n";
					newFocus->completionReward += "					limit = {\n";
					newFocus->completionReward += "						" + Home->getTag() + " = {\n";
					newFocus->completionReward += "							has_government = democratic\n";
					newFocus->completionReward += "						}\n";
					newFocus->completionReward += "					}\n";
					newFocus->completionReward += "					add_ideas = democratic_influence\n";
					newFocus->completionReward += "				}\n";
				}
				if (majorIdeologies.count("absolutist") > 0)
				{
					newFocus->completionReward += "				if = {\n";
					newFocus->completionReward += "					limit = {\n";
					newFocus->completionReward += "						" + Home->getTag() + " = {\n";
					newFocus->completionReward += "							has_government = absolutist\n";
					newFocus->completionReward += "						}\n";
					newFocus->completionReward += "					}\n";
					newFocus->completionReward += "					add_ideas = absolutist_influence\n";
					newFocus->completionReward += "				}\n";
				}
				if (majorIdeologies.count("radical") > 0)
				{
					newFocus->completionReward += "				if = {\n";
					newFocus->completionReward += "					limit = {\n";
					newFocus->completionReward += "						" + Home->getTag() + " = {\n";
					newFocus->completionReward += "							has_government = radical\n";
					newFocus->completionReward += "						}\n";
					newFocus->completionReward += "					}\n";
					newFocus->completionReward += "					add_ideas = radical_influence\n";
					newFocus->completionReward += "				}\n";
				}
				newFocus->completionReward += "				country_event = { id = generic.1 }\n";
				newFocus->completionReward += "			}\n";
				newFocus->completionReward += "		}";
				focuses.push_back(newFocus);

				//Civil War
				newFocus = loadedFocuses.find("Coup_")->second.makeCustomizedCopy(Home->getTag());
				newFocus->id = "Coup_" + coupTargets[i]->getTag() + "_" + Home->getTag();
				newFocus->text = "Civil War in " + coupCountryName;
				newFocus->prerequisites.push_back("= { focus = Influence_" + coupTargets[i]->getTag() + "_" + Home->getTag() + " }");
				newFocus->relativePositionId = "Influence_" + coupTargets[i]->getTag() + "_" + Home->getTag();
				newFocus->xPos = 0;
				newFocus->yPos = 1;
				newFocus->available = "= {\n";
				newFocus->available += "			" + coupTargets[i]->getTag() + " = { communism > 0.5 }\n";
				newFocus->available += "		}";
				newFocus->completionReward += "= {\n";
				newFocus->completionReward += "			" + coupTargets[i]->getTag() + " = {\n";
				newFocus->completionReward += "				start_civil_war = {\n";
				newFocus->completionReward += "					ideology = communism\n";
				newFocus->completionReward += "					size = 0.5\n";
				newFocus->completionReward += "				}\n";
				newFocus->completionReward += "			}\n";
				newFocus->completionReward += "		}";
				focuses.push_back(newFocus);
			}
		}
		nextFreeColumn += 2 * coupTargets.size();
	}
	return;
}

void HoI4FocusTree::addCommunistWarBranch(shared_ptr<HoI4Country> Home, const vector<shared_ptr<HoI4Country>>& warTargets, HoI4::Events* events)
{
	if (warTargets.size() > 0)
	{

		//Strengthen Commintern
		shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("StrengthCom")->second.makeCustomizedCopy(Home->getTag());
		newFocus->xPos = nextFreeColumn + warTargets.size() - 1;
		newFocus->yPos = 0;
		focuses.push_back(newFocus);

		newFocus = loadedFocuses.find("Inter_Com_Pres")->second.makeCustomizedCopy(Home->getTag());
		newFocus->relativePositionId = "StrengthCom" + Home->getTag();
		newFocus->xPos = 0;
		newFocus->yPos = 1;
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			add_named_threat = { threat = 2 name = " + newFocus->id + " }\n";
		newFocus->completionReward += "		}";
		//FIXME
		//maybe add some claims?
		focuses.push_back(newFocus);

		for (unsigned int i = 0; i < 3; i++)
		{
			if (i < warTargets.size())
			{
				auto possibleWarTargetCountryName = warTargets[i]->getSourceCountry()->getName("english");
				string warTargetCountryName;
				if (possibleWarTargetCountryName)
				{
					warTargetCountryName = *possibleWarTargetCountryName;
				}
				else
				{
					LOG(LogLevel::Warning) << "Could not determine war target country name for communist war focuses";
					warTargetCountryName = "";
				}

				int v1 = rand() % 12 + 1;
				int v2 = rand() % 12 + 1;
				newFocus = loadedFocuses.find("War")->second.makeCustomizedCopy(Home->getTag());
				newFocus->id = "War" + warTargets[i]->getTag() + Home->getTag();
				newFocus->text = "War with " + warTargetCountryName;//change to faction name later
				newFocus->available = "= {\n";
				newFocus->available += "			date > 1938." + to_string(v1) + "." + to_string(v2) + "\n";
				newFocus->available += "		}";
				newFocus->xPos = nextFreeColumn + i * 2;
				newFocus->yPos = 2;
				newFocus->bypass = "= {\n";
				newFocus->bypass += "					has_war_with = " + warTargets[i]->getTag() + "\n";
				newFocus->bypass += "				}";
				newFocus->aiWillDo = "= {\n";
				newFocus->aiWillDo += "			factor = 5\n";
				newFocus->aiWillDo += "			modifier = {\n";
				newFocus->aiWillDo += "				factor = 0\n";
				newFocus->aiWillDo += "				strength_ratio = { tag = " + warTargets[i]->getTag() + " ratio < 1 }\n";
				newFocus->aiWillDo += "			}";
				if (warTargets.size() > 1)
				{
					newFocus->aiWillDo += "\n";
					newFocus->aiWillDo += "			modifier = {\n";
					newFocus->aiWillDo += "				factor = 0\n";
					newFocus->aiWillDo += "				OR = {\n";
					for (unsigned int i2 = 0; i2 < warTargets.size(); i2++)
					{
						if (i != i2)
							newFocus->aiWillDo += "					has_war_with = " + warTargets[i]->getTag() + "\n";
					}
					newFocus->aiWillDo += "				}\n";
					newFocus->aiWillDo += "			}";
				}
				newFocus->aiWillDo += "\n";
				newFocus->aiWillDo += "		}";

				newFocus->completionReward += "= {\n";
				newFocus->completionReward += "			add_named_threat = { threat = 3 name = " + newFocus->id + " }\n";
				newFocus->completionReward += "			create_wargoal = {\n";
				newFocus->completionReward += "				type = puppet_wargoal_focus\n";
				newFocus->completionReward += "				target = " + warTargets[i]->getTag() + "\n";
				newFocus->completionReward += "			}\n";
				newFocus->completionReward += "		}";
				focuses.push_back(newFocus);
			}
		}
		nextFreeColumn += warTargets.size() * 2;
	}
}

void HoI4FocusTree::addFascistAnnexationBranch(shared_ptr<HoI4Country> Home, const vector<shared_ptr<HoI4Country>>& annexationTargets, HoI4::Events* events)
{
	//The Following 'if' statement prevents converter from generating focuses if annexationTargets.size > 1
	//Keep this 'if' statement off until we figure out how to handle Fascist NF's
	//if (annexationTargets.size() >= 1)
	//{
	//Focus to increase fascist support and prereq for anschluss
	shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("The_third_way")->second.makeCustomizedCopy(Home->getTag());
	if (annexationTargets.size() >= 1)
	{
		newFocus->xPos = nextFreeColumn + annexationTargets.size() - 1;
	}

	//'else' statement is there in case annexationTargets.size() is <1.  Need to fix in the future.
	else
	{
		newFocus->xPos = nextFreeColumn;
	}
	newFocus->yPos = 0;
	//FIXME
	//Need to get Drift Defense to work
	//in modified generic focus? (tk)
	//newFocus->completionReward += "			drift_defence_factor = 0.5\n";
	newFocus->completionReward += "= {\n";
	newFocus->completionReward += "			add_named_threat = { threat = 2 name = " + newFocus->id + " }\n";
	newFocus->completionReward += "			add_ideas = fascist_influence\n";
	newFocus->completionReward += "		}";
	focuses.push_back(newFocus);

	//Focus to increase army support
	newFocus = loadedFocuses.find("mil_march")->second.makeCustomizedCopy(Home->getTag());
	newFocus->relativePositionId = "The_third_way" + Home->getTag();
	newFocus->xPos = 0;
	newFocus->yPos = 1;
	focuses.push_back(newFocus);

	for (unsigned int i = 0; i < annexationTargets.size(); i++)
	{
		if (i < annexationTargets.size())
		{
			auto possibleAnnexationTargetCountryName = annexationTargets[i]->getSourceCountry()->getName("english");
			string annexationTargetCountryName;
			if (possibleAnnexationTargetCountryName)
			{
				annexationTargetCountryName = *possibleAnnexationTargetCountryName;
			}
			else
			{
				LOG(LogLevel::Warning) << "Could not determine annexation target country name for fascist annexation focuses";
				annexationTargetCountryName = "";
			}

			//int x = i * 3;
			//for random date
			int v1 = rand() % 5 + 1;
			int v2 = rand() % 5 + 1;
			//focus for anschluss
			newFocus = loadedFocuses.find("_anschluss_")->second.makeCustomizedCopy(Home->getTag());
			newFocus->id = Home->getTag() + "_anschluss_" + annexationTargets[i]->getTag();
			newFocus->text = "Union with " + annexationTargetCountryName;
			newFocus->available += "= {\n";
			newFocus->available += "			" + annexationTargets[i]->getTag() + " = {\n";
			newFocus->available += "				is_in_faction = no\n";
			newFocus->available += "			}\n";
			newFocus->available += "			is_puppet = no\n";
			newFocus->available += "			date > 1937." + to_string(v1 + 5) + "." + to_string(v2 + 5) + "\n";
			newFocus->available += "		}";
			newFocus->xPos = nextFreeColumn + i * 2;
			newFocus->yPos = 2;
			newFocus->completionReward += "= {\n";
			newFocus->completionReward += "			add_named_threat = { threat = 2 name = " + newFocus->id + " }\n";
			newFocus->completionReward += "			army_experience = 10\n";
			newFocus->completionReward += "			if = {\n";
			newFocus->completionReward += "				limit = {\n";
			newFocus->completionReward += "					country_exists = " + annexationTargets[i]->getTag() + "\n";
			newFocus->completionReward += "				}\n";
			newFocus->completionReward += "				" + annexationTargets[i]->getTag() + " = {\n";
			newFocus->completionReward += "					country_event = NFEvents." + to_string(events->getCurrentNationFocusEventNum()) + "\n";
			newFocus->completionReward += "				}\n";
			newFocus->completionReward += "			}\n";
			newFocus->completionReward += "		}";
			focuses.push_back(newFocus);

			events->createAnnexEvent(Home, annexationTargets[i]);
		}
	}
	if (annexationTargets.size() >= 1)
	{
		nextFreeColumn += annexationTargets.size() * 2;
	}
	else
	{
		nextFreeColumn += 2;
	}
	//}
}

void HoI4FocusTree::addFascistSudetenBranch(shared_ptr<HoI4Country> Home, const vector<shared_ptr<HoI4Country>>& sudetenTargets, const vector<vector<int>>& demandedStates, const HoI4::World* world)
{
	HoI4::Events* events = world->getEvents();

	//if it can easily take these targets as they are not in an alliance, you can get annexation event

	//Focus to increase empire size more
	shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("expand_the_reich")->second.makeCustomizedCopy(Home->getTag());
	//newFocus->icon = "GFX_goal_generic_political_pressure";  //something about claiming land
	if (sudetenTargets.size() == 1 || sudetenTargets.size() >= 2)
	{
		//if there are anschlusses, make this event require at least 1 anschluss, else, its the start of a tree
		for (unsigned int i = 0; i < 2; i++)
		{
			if (i < sudetenTargets.size())
			{
				//					newFocus->prerequisites.push_back("= { focus = " + Home->getTag() + "_anschluss_" + sudetenTargets[i]->getTag() + " }");
			}
		}
		newFocus->xPos = nextFreeColumn + sudetenTargets.size() - 1;
	}

	//'else' statement is there in case sudetenTargets.size() is <1.  Need to fix in the future.
	else
	{
		newFocus->xPos = nextFreeColumn;
	}
	newFocus->yPos = 0;
	newFocus->completionReward += "= {\n";
	newFocus->completionReward += "			add_named_threat = { threat = 3 name = " + newFocus->id + " }\n";//give some claims or cores
	newFocus->completionReward += "		}";
	addFocus(newFocus);

	for (unsigned int i = 0; i < sudetenTargets.size(); i++)
	{
		if (i < sudetenTargets.size())
		{
			auto possibleSudetenTargetCountryName = sudetenTargets[i]->getSourceCountry()->getName("english");
			string sudetenTargetCountryName;
			if (possibleSudetenTargetCountryName)
			{
				sudetenTargetCountryName = *possibleSudetenTargetCountryName;
			}
			else
			{
				LOG(LogLevel::Warning) << "Could not determine annexation target country name for fascist sudeten focuses";
				sudetenTargetCountryName = "";
			}

			int v1 = rand() % 8 + 1;
			int v2 = rand() % 8 + 1;
			//focus for sudaten
			newFocus = loadedFocuses.find("_sudeten_")->second.makeCustomizedCopy(Home->getTag());
			newFocus->id = Home->getTag() + "_sudeten_" + sudetenTargets[i]->getTag();
			newFocus->text = "Demand Territory from " + sudetenTargetCountryName;
			newFocus->available = "= {\n";
			newFocus->available += "			is_puppet = no\n";
			newFocus->available += "			date > 1938." + to_string(v1) + "." + to_string(v2) + "\n";
			newFocus->available += "		}";
			newFocus->xPos = nextFreeColumn + 2 * i;
			newFocus->yPos = 1;
			newFocus->bypass += "= {\n";
			newFocus->bypass += "  has_war_with = " + sudetenTargets[i]->getTag() + "\n";
			newFocus->bypass += "}";
			newFocus->completionReward += "= {\n";
			newFocus->completionReward += "			add_named_threat = { threat = 2 name = " + newFocus->id + " }\n";
			newFocus->completionReward += "			army_experience = 10\n";
			newFocus->completionReward += "			if = {\n";
			newFocus->completionReward += "				limit = {\n";
			newFocus->completionReward += "					country_exists = " + sudetenTargets[i]->getTag() + "\n";
			newFocus->completionReward += "				}\n";
			newFocus->completionReward += "				" + sudetenTargets[i]->getTag() + " = {\n";
			newFocus->completionReward += "					country_event = NFEvents." + to_string(events->getCurrentNationFocusEventNum()) + "\n";
			newFocus->completionReward += "				}\n";
			newFocus->completionReward += "			}\n";
			newFocus->completionReward += "		}";
			addFocus(newFocus);

			//FINISH HIM
			newFocus = loadedFocuses.find("_finish_")->second.makeCustomizedCopy(Home->getTag());
			newFocus->id = Home->getTag() + "_finish_" + sudetenTargets[i]->getTag();
			newFocus->text = "Fate of " + sudetenTargetCountryName;
			newFocus->available = sudetenTargets[i]->getTag() + " = { is_in_faction = no }";
			newFocus->prerequisites.push_back("= { focus =  " + Home->getTag() + "_sudeten_" + sudetenTargets[i]->getTag() + " }");
			newFocus->xPos = nextFreeColumn + 2 * i;
			newFocus->yPos = 2;
			newFocus->bypass += "= {\n";
			newFocus->bypass += "		has_war_with = " + sudetenTargets[i]->getTag() + "\n";
			newFocus->bypass += "	}";
			newFocus->completionReward += "= {\n";
			newFocus->completionReward += "			add_named_threat = { threat = 3 name = " + newFocus->id + " }\n";
			newFocus->completionReward += "			create_wargoal = {\n";
			newFocus->completionReward += "				type = annex_everything\n";
			newFocus->completionReward += "				target = " + sudetenTargets[i]->getTag() + "\n";
			newFocus->completionReward += "			}\n";
			newFocus->completionReward += "		}";
			addFocus(newFocus);

			//events
			events->createSudetenEvent(Home, sudetenTargets[i], demandedStates[i]);
		}
	}
	nextFreeColumn += 2 * sudetenTargets.size();
}

void HoI4FocusTree::addGPWarBranch(shared_ptr<HoI4Country> Home, const vector<shared_ptr<HoI4Country>>& newAllies, const vector<shared_ptr<HoI4Country>>& GCTargets, const string& ideology, HoI4::Events* events)
{
	int numAllies = newAllies.size();
	string ideologyShort = ideology.substr(0, 3);
	if (newAllies.size() > 0)
	{
		//Focus to call summit, maybe have events from summit
		shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("_Summit")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id = ideologyShort + "_Summit" + Home->getTag();
		newFocus->text = "Call for the " + ideology + " Summit";
		if (numAllies = 0)
		{
			newFocus->xPos = nextFreeColumn + newAllies.size();
		}
		else
		{
			newFocus->xPos = nextFreeColumn + newAllies.size() + 1;
		}
		newFocus->yPos = 0;
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			add_named_threat = { threat = 3 name = " + newFocus->id + " }\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
	}

	unsigned int i = 0;
	for (auto newAlly : newAllies)
	{
		auto possibleAllyCountryName = newAlly->getSourceCountry()->getName("english");
		string allyCountryName;
		if (possibleAllyCountryName)
		{
			allyCountryName = *possibleAllyCountryName;
		}
		else
		{
			LOG(LogLevel::Warning) << "Could not determine ally country name for GP alliance focuses";
			allyCountryName = "";
		}

		shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("Alliance_")->second.makeCustomizedCopy(Home->getTag());
		newFocus->id = "Alliance_" + newAlly->getTag() + Home->getTag();
		newFocus->text = "Alliance with " + allyCountryName;
		newFocus->prerequisites.push_back("= { focus = " + ideologyShort + "_Summit" + Home->getTag() + " }");
		newFocus->relativePositionId = ideologyShort + "_Summit" + Home->getTag();
		if (numAllies == 1)
		{
			newFocus->xPos = 0;
		}
		else
		{
			newFocus->xPos = (i * 2) - 1;
		}
		newFocus->yPos = 1;
		newFocus->bypass += "= {\n";
		newFocus->bypass += "			OR = {\n";
		newFocus->bypass += "				" + Home->getTag() + " = { is_in_faction_with = " + newAlly->getTag() + "}\n";
		newFocus->bypass += "				has_war_with = " + newAlly->getTag() + "\n";
		newFocus->bypass += "				NOT = { country_exists = " + newAlly->getTag() + " }\n";
		newFocus->bypass += "			}\n";
		newFocus->bypass += "		}";
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			" + newAlly->getTag() + " = {\n";
		newFocus->completionReward += "				country_event = { hours = 6 id = NFEvents." + to_string(events->getCurrentNationFocusEventNum()) + " }\n";
		newFocus->completionReward += "				add_opinion_modifier = { target = " + Home->getTag() + " modifier = positive_50 }\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);

		events->createFactionEvents(Home, newAlly);
		i++;
	}

	i = 0;
	for (auto GC : GCTargets)
	{
		auto possibleWarTargetCountryName = GC->getSourceCountry()->getName("english");
		string warTargetCountryName;
		if (possibleWarTargetCountryName)
		{
			warTargetCountryName = *possibleWarTargetCountryName;
		}
		else
		{
			LOG(LogLevel::Warning) << "Could not determine war target country name for GP war focuses";
			warTargetCountryName = "";
		}

		string prereq = "";
		int y2 = 1;
		//figuring out location of WG
		shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("GP_War")->second.makeCustomizedCopy(Home->getTag());
		if (newAllies.size() > 0)
		{
			y2 = 2;
			for (unsigned int i2 = 0; i2 < newAllies.size(); i2++)
			{
				newFocus->prerequisites.push_back("= { focus = Alliance_" + newAllies[i2]->getTag() + Home->getTag() + " }");
			}
		}
		int v1 = rand() % 12 + 1;
		int v2 = rand() % 12 + 1;
		newFocus->id = "GP_War" + GC->getTag() + Home->getTag();
		newFocus->text = "War with " + warTargetCountryName;//change to faction name later
		newFocus->available = "= {\n";
		newFocus->available += "			has_war = no\n";
		newFocus->available += "			date > 1939." + to_string(v1) + "." + to_string(v2) + "\n";
		newFocus->available += "		}";
		newFocus->relativePositionId = ideologyShort + "_Summit" + Home->getTag();
		newFocus->xPos = 0;
		newFocus->yPos = 2;
		newFocus->bypass = "= {\n";
		newFocus->bypass += "		   has_war_with = " + GC->getTag() + "\n";
		newFocus->bypass += "		}";
		newFocus->aiWillDo = "= {\n";
		newFocus->aiWillDo += "			factor = " + to_string(10 - GCTargets.size() * 5) + "\n";
		newFocus->aiWillDo += "			modifier = {\n";
		newFocus->aiWillDo += "					factor = 0\n";
		newFocus->aiWillDo += "					strength_ratio = { tag = " + GC->getTag() + " ratio < 1 }\n";
		newFocus->aiWillDo += "			}";
		if (GCTargets.size() > 1)
		{
			newFocus->aiWillDo = "\n";

			//make ai have this as a 0 modifier if they are at war
			newFocus->aiWillDo += "			modifier = {\n";
			newFocus->aiWillDo += "				factor = 0\n";
			newFocus->aiWillDo += "				OR = {\n";
			for (unsigned int i2 = 0; i2 < GCTargets.size(); i2++)
			{
				if (GC != GCTargets[i2])
				{
					newFocus->aiWillDo += "					has_war_with = " + GCTargets[i2]->getTag() + "\n";
				}
			}
			newFocus->aiWillDo += "				}\n";
			newFocus->aiWillDo += "			}";
		}
		newFocus->aiWillDo += "\n";
		newFocus->aiWillDo += "		}";
		newFocus->completionReward += "= {\n";
		newFocus->completionReward += "			add_named_threat = { threat = 5 name = " + newFocus->id + " }\n";
		newFocus->completionReward += "			declare_war_on = {\n";
		newFocus->completionReward += "				type = puppet_wargoal_focus\n";
		newFocus->completionReward += "				target = " + GC->getTag() + "\n";
		newFocus->completionReward += "			}\n";
		newFocus->completionReward += "		}";
		focuses.push_back(newFocus);
		i++;
	}
	nextFreeColumn += 2 * max(newAllies.size(), GCTargets.size());
}

void HoI4FocusTree::addNeighborWarBranch(const string& tag, const vector<shared_ptr<HoI4Country>>& weakNeighbors, const shared_ptr<HoI4Country>& targetNeighbors, const string targetName, const date startDate, int numWarsWithNeighbors)
{
	shared_ptr<HoI4Focus> newFocus = loadedFocuses.find("NeighborWar")->second.makeCustomizedCopy(tag);
	newFocus->id = "NeighborWar" + targetNeighbors->getTag() + tag;
	newFocus->text = "War with " + targetName;//change to faction name later
	newFocus->available = "= {\n";
	newFocus->available += "			has_war = no\n";
	newFocus->available += "			date > " + startDate.toString() + "\n";
	newFocus->available += "		}";
	newFocus->xPos = nextFreeColumn;
	newFocus->yPos = 0;
	newFocus->bypass = "= {\n";
	newFocus->bypass += "			has_war_with = " + targetNeighbors->getTag() + "\n";
	newFocus->bypass += "		}";
	newFocus->aiWillDo = "= {\n";
	newFocus->aiWillDo += "			factor = " + to_string(10 - numWarsWithNeighbors * 5) + "\n";
	newFocus->aiWillDo += "			modifier = {\n";
	newFocus->aiWillDo += "				factor = 0\n";
	newFocus->aiWillDo += "				strength_ratio = { tag = " + targetNeighbors->getTag() + " ratio < 0.8 }\n";
	newFocus->aiWillDo += "			}";
	if (weakNeighbors.size() > 2) //make ai have this as a 0 modifier if they are at war
	{
		newFocus->aiWillDo += "\n";
		newFocus->aiWillDo += "			modifier = {\n";
		newFocus->aiWillDo += "				factor = 0\n";
		newFocus->aiWillDo += "				OR = {\n";
		for (auto target2 : weakNeighbors)
		{
			if (targetNeighbors != target2)
			{
				newFocus->aiWillDo += "					has_war_with = " + target2->getTag() + "\n";
			}
		}
		newFocus->aiWillDo += "				}\n";
		newFocus->aiWillDo += "			}";
	}
	newFocus->aiWillDo += "\n";
	newFocus->aiWillDo += "		}";
	newFocus->completionReward += "= {\n";
	newFocus->completionReward += "			add_named_threat = { threat = 3 name = " + newFocus->id + " }\n";
	newFocus->completionReward += "			create_wargoal = {\n";
	newFocus->completionReward += "				type = annex_everything\n";
	newFocus->completionReward += "				target = " + targetNeighbors->getTag() + "\n";
	newFocus->completionReward += "			}\n";
	newFocus->completionReward += "		}";
	focuses.push_back(newFocus);
}

void HoI4FocusTree::removeFocus(const string& id)
{
	for (auto itr = focuses.begin(); itr != focuses.end(); itr++)
	{
		if ((*itr)->id == id)
		{
			focuses.erase(itr);
			break;
		}
	}
}

void HoI4FocusTree::output(const string& filename) const
{
	ofstream out(filename);
	if (!out.is_open())
	{
		LOG(LogLevel::Error) << "Could not create " << filename;
		exit(-1);
	}

	out << "focus_tree = {\n";
	if (dstCountryTag != "")
	{
		out << "	id = " << dstCountryTag + "_focus\n";
		out << "	\n";
		out << "	country = {\n";
		out << "		factor = 0\n";
		out << "		\n";
		out << "		modifier = {\n";
		out << "			add = 10\n";
		out << "			tag = " << dstCountryTag << "\n";
		out << "		}\n";
		out << "	}\n";
		out << "	\n";
		out << "	default = no\n";
		out << "\n";
	}
	else
	{
		out << "	id = generic_focus\n";
		out << "	\n";
		out << "	country = {\n";
		out << "		factor = 1\n";
		out << "	}\n";
		out << "	\n";
		out << "	default = yes\n";
		out << "	reset_on_civilwar = no\n";
		out << "\n";
	}

	for (auto focus : focuses)
	{
		out << *focus;
		out << "\n";
	}

	out << "}";

	out.close();
}

extension: cpp


text:
package main

import (
	"fmt"
	"time"
)

// Pinger func prints "ping" and wait for a "pong"
func pinger(pinger <-chan int, ponger chan int) {
	for {
		<-pinger
		fmt.Println("ping")
		time.Sleep(time.Second)
		ponger <- 1
	}
}

// Ponger func prints "pong" and wait for a "ping"
func ponger(pinger chan int, ponger <-chan int) {
	for {
		<-ponger
		fmt.Println("pong")
		time.Sleep(time.Second)
		pinger <- 1
	}
}

func main() {
	ping := make(chan int)
	pong := make(chan int)

	go pinger(ping, pong)
	go ponger(ping, pong)

	// Main goroutine starts the ping/pong by sending 1 into the ping chan
	ping <- 1

	for {
		// Block main thread until an interrupt
		time.Sleep(time.Second)
	}

}

repository: PiterPentester/GetGoing

repo_name: PiterPentester/GetGoing


text:
// SPDX-License-Identifier: Unlicense OR MIT

package app

import (
	"errors"
	"fmt"
	"image"
	"time"

	"gioui.org/ui"
	"gioui.org/ui/app/internal/gpu"
	iinput "gioui.org/ui/app/internal/input"
	"gioui.org/ui/input"
	"gioui.org/ui/system"
)

// WindowOption configures a Window.
type WindowOption struct {
	apply func(opts *windowOptions)
}

type windowOptions struct {
	Width, Height ui.Value
	Title         string
}

// Window represents an operating system window.
type Window struct {
	driver    *window
	lastFrame time.Time
	drawStart time.Time
	gpu       *gpu.GPU

	out         chan input.Event
	in          chan input.Event
	ack         chan struct{}
	invalidates chan struct{}
	frames      chan *ui.Ops

	stage        Stage
	animating    bool
	hasNextFrame bool
	nextFrame    time.Time
	delayedDraw  *time.Timer

	queue Queue
}

// Queue is an input.Queue implementation that distributes
// system input events to the input handlers declared in the
// most recent call to Update.
type Queue struct {
	q iinput.Router
}

// driverEvent is sent when a new native driver
// is available for the Window.
type driverEvent struct {
	driver *window
}

// driver is the interface for the platform implementation
// of a Window.
var _ interface {
	// setAnimating sets the animation flag. When the window is animating,
	// UpdateEvents are delivered as fast as the display can handle them.
	setAnimating(anim bool)
	// showTextInput updates the virtual keyboard state.
	showTextInput(show bool)
} = (*window)(nil)

// Pre-allocate the ack event to avoid garbage.
var ackEvent input.Event

// NewWindow creates a new window for a set of window
// options. The options are hints; the platform is free to
// ignore or adjust them.
//
// If opts are nil, a set of sensible defaults are used.
//
// If the current program is running on iOS and Android,
// NewWindow returns the window previously created by the
// platform.
//
// BUG: Calling NewWindow more than once is not yet supported.
func NewWindow(options ...WindowOption) *Window {
	opts := &windowOptions{
		Width:  ui.Dp(800),
		Height: ui.Dp(600),
		Title:  "Gio",
	}

	for _, o := range options {
		o.apply(opts)
	}

	w := &Window{
		in:          make(chan input.Event),
		out:         make(chan input.Event),
		ack:         make(chan struct{}),
		invalidates: make(chan struct{}, 1),
		frames:      make(chan *ui.Ops),
	}
	go w.run(opts)
	return w
}

// Events returns the channel where events are delivered.
func (w *Window) Events() <-chan input.Event {
	return w.out
}

// Queue returns the Window's event queue. The queue contains
// the events received since the last UpdateEvent.
func (w *Window) Queue() *Queue {
	return &w.queue
}

// Update updates the Window. Paint operations updates the
// window contents, input operations declare input handlers,
// and so on. The supplied operations list completely replaces
// the window state from previous calls.
func (w *Window) Update(frame *ui.Ops) {
	w.frames <- frame
}

func (w *Window) draw(size image.Point, frame *ui.Ops) {
	var drawDur time.Duration
	if !w.drawStart.IsZero() {
		drawDur = time.Since(w.drawStart)
		w.drawStart = time.Time{}
	}
	w.gpu.Draw(w.queue.q.Profiling(), size, frame)
	w.queue.q.Frame(frame)
	now := time.Now()
	switch w.queue.q.TextInputState() {
	case iinput.TextInputOpen:
		w.driver.showTextInput(true)
	case iinput.TextInputClose:
		w.driver.showTextInput(false)
	}
	frameDur := now.Sub(w.lastFrame)
	frameDur = frameDur.Truncate(100 * time.Microsecond)
	w.lastFrame = now
	if w.queue.q.Profiling() {
		q := 100 * time.Microsecond
		timings := fmt.Sprintf("tot:%7s cpu:%7s %s", frameDur.Round(q), drawDur.Round(q), w.gpu.Timings())
		w.queue.q.AddProfile(system.ProfileEvent{Timings: timings})
		w.setNextFrame(time.Time{})
	}
	if t, ok := w.queue.q.WakeupTime(); ok {
		w.setNextFrame(t)
	}
	w.updateAnimation()
}

// Invalidate the window such that a UpdateEvent will be generated
// immediately. If the window is inactive, the event is sent when the
// window becomes active.
func (w *Window) Invalidate() {
	select {
	case w.invalidates <- struct{}{}:
	default:
	}
}

func (w *Window) updateAnimation() {
	animate := false
	if w.delayedDraw != nil {
		w.delayedDraw.Stop()
		w.delayedDraw = nil
	}
	if w.stage >= StageRunning && w.hasNextFrame {
		if dt := time.Until(w.nextFrame); dt <= 0 {
			animate = true
		} else {
			w.delayedDraw = time.NewTimer(dt)
		}
	}
	if animate != w.animating {
		w.animating = animate
		w.driver.setAnimating(animate)
	}
}

func (w *Window) setNextFrame(at time.Time) {
	if !w.hasNextFrame || at.Before(w.nextFrame) {
		w.hasNextFrame = true
		w.nextFrame = at
	}
}

func (w *Window) setDriver(d *window) {
	w.event(driverEvent{d})
}

func (w *Window) event(e input.Event) {
	w.in <- e
	<-w.ack
}

func (w *Window) waitAck() {
	// Send a dummy event; when it gets through we
	// know the application has processed the previous event.
	w.out <- ackEvent
}

// Prematurely destroy the window and wait for the native window
// destroy event.
func (w *Window) destroy(err error) {
	// Ack the current event.
	w.ack <- struct{}{}
	w.out <- DestroyEvent{err}
	for e := range w.in {
		w.ack <- struct{}{}
		if _, ok := e.(DestroyEvent); ok {
			return
		}
	}
}

func (w *Window) run(opts *windowOptions) {
	defer close(w.in)
	defer close(w.out)
	if err := createWindow(w, opts); err != nil {
		w.out <- DestroyEvent{err}
		return
	}
	for {
		var timer <-chan time.Time
		if w.delayedDraw != nil {
			timer = w.delayedDraw.C
		}
		select {
		case <-timer:
			w.setNextFrame(time.Time{})
			w.updateAnimation()
		case <-w.invalidates:
			w.setNextFrame(time.Time{})
			w.updateAnimation()
		case e := <-w.in:
			switch e2 := e.(type) {
			case StageEvent:
				if w.gpu != nil {
					if e2.Stage < StageRunning {
						w.gpu.Release()
						w.gpu = nil
					} else {
						w.gpu.Refresh()
					}
				}
				w.stage = e2.Stage
				w.updateAnimation()
				w.out <- e
				w.waitAck()
			case UpdateEvent:
				if e2.Size == (image.Point{}) {
					panic(errors.New("internal error: zero-sized Draw"))
				}
				if w.stage < StageRunning {
					// No drawing if not visible.
					break
				}
				w.drawStart = time.Now()
				w.hasNextFrame = false
				w.out <- e
				var frame *ui.Ops
				// Wait for either a frame or the ack event,
				// which meant that the client didn't draw.
				select {
				case frame = <-w.frames:
				case w.out <- ackEvent:
				}
				if w.gpu != nil {
					if e2.sync {
						w.gpu.Refresh()
					}
					if err := w.gpu.Flush(); err != nil {
						w.gpu.Release()
						w.gpu = nil
						w.destroy(err)
						return
					}
				} else {
					ctx, err := newContext(w.driver)
					if err != nil {
						w.destroy(err)
						return
					}
					w.gpu, err = gpu.NewGPU(ctx)
					if err != nil {
						w.destroy(err)
						return
					}
				}
				w.draw(e2.Size, frame)
				if e2.sync {
					if err := w.gpu.Flush(); err != nil {
						w.gpu.Release()
						w.gpu = nil
						w.destroy(err)
						return
					}
				}
			case *CommandEvent:
				w.out <- e
				w.waitAck()
			case driverEvent:
				w.driver = e2.driver
			case DestroyEvent:
				w.out <- e2
				w.ack <- struct{}{}
				return
			case input.Event:
				if w.queue.q.Add(e2) {
					w.setNextFrame(time.Time{})
					w.updateAnimation()
				}
				w.out <- e
			}
			w.ack <- struct{}{}
		}
	}
}

func (q *Queue) Next(k input.Key) (input.Event, bool) {
	return q.q.Next(k)
}

// WithTitle returns an option that sets the window title.
func WithTitle(t string) WindowOption {
	return WindowOption{
		apply: func(opts *windowOptions) {
			opts.Title = t
		},
	}
}

// WithWidth returns an option that sets the window width.
func WithWidth(w ui.Value) WindowOption {
	if w.V <= 0 {
		panic("width must be larger than or equal to 0")
	}
	return WindowOption{
		apply: func(opts *windowOptions) {
			opts.Width = w
		},
	}
}

// WithHeight returns an option that sets the window height.
func WithHeight(h ui.Value) WindowOption {
	if h.V <= 0 {
		panic("height must be larger than or equal to 0")
	}
	return WindowOption{
		apply: func(opts *windowOptions) {
			opts.Height = h
		},
	}
}

func (driverEvent) ImplementsEvent() {}

license: MIT,Unlicense

repository: kasperlewau/gio

detected_licenses: MIT Unlicense

repo_name: kasperlewau/gio


text:
@article{kjaergard_association_2002,
	title = {Association between competing interests and authors' conclusions: epidemiological study of randomised clinical trials published in the {BMJ}},
	volume = {325},
	issn = {09598138},
	url = {http://www.bmj.com/cgi/doi/10.1136/bmj.325.7358.249},
	doi = {10.1136/bmj.325.7358.249},
	shorttitle = {Association between competing interests and authors' conclusions},
	abstract = {Description: This article notes that publications noting financial competing interests led to different reporting results compared to publications reporting no competing interests. This effect could not be explained by methodological quality or other factors. Interestingly, publications reporting other types of competing interests did not differ in reporting results. Abstract "Objective: To assess the association between competing interests and authors' conclusions in randomised clinical trials. Design: Epidemiological study of randomised clinical trials published in the {BMJ} from January 1997 to June 2001. Financial competing interests were defined as funding by for profit organisations and other competing interests as personal, academic, or political. Studies: 159 trials from 12 medical specialties. Main outcome measures: Authors' conclusions defined as interpretation of extent to which overall results favoured experimental intervention. Conclusions appraised on 6 point scale; higher scores favour experimental intervention. Results: Authors' conclusions were significantly more positive towards the experimental intervention in trials funded by for profit organisations alone compared with trials without competing interests (mean difference 0.48 ({SE} 0.13), P=0.014), trials funded by both for profit and non-profit organisations (0.30 ({SE} 0.10), P=0.003), and trials with other competing interests (0.45 ({SE} 0.13), P=0.006). Other competing interests and funding from both for profit and non-profit organisations were not significantly associated with authors' conclusions. The association between financial competing interests and authors' conclusions was not explained by methodological quality, statistical power, type of experimental intervention (pharmacological or non-pharmacological), type of control intervention (for example, placebo or active drug), or medical specialty. Conclusions: Authors' conclusions in randomised clinical trials significantly favoured experimental interventions if financial competing interests were declared. Other competing interests were not significantly associated with authors' conclusions."},
	pages = {249--249},
	number = {7358},
	journaltitle = {{BMJ}},
	author = {Kjaergard, L. L},
	urldate = {2011-04-04},
	date = {2002-08}
}

repository: pmean/build-website

repo_name: pmean/build-website