text:
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Package ui enables interacting with the ChromeOS UI through the chrome.automation API.
// The chrome.automation API is documented here: https://developer.chrome.com/extensions/automation
package ui

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"regexp"
	"time"

	"github.com/google/go-cmp/cmp"

	"chromiumos/tast/errors"
	"chromiumos/tast/local/chrome"
	"chromiumos/tast/local/chrome/ui/mouse"
	"chromiumos/tast/local/coords"
	"chromiumos/tast/testing"
)

// FindParams is a mapping of chrome.automation.FindParams to Golang.
// Name and ClassName allow quick access because they are common attributes.
// As defined in chromium/src/extensions/common/api/automation.idl
type FindParams struct {
	Role       RoleType
	Name       string
	ClassName  string
	Attributes map[string]interface{}
	State      map[StateType]bool
}

// rawAttributes creates a byte array of the attributes field.
// It adds the quick attributes(Name and ClassName) to it as well.
// If any attribute is defined twice, an error is returned.
// This function is for use in rawBytes.
func (params *FindParams) rawAttributes() ([]byte, error) {
	attributes := make(map[string]interface{})
	if params.Attributes != nil {
		for k, v := range params.Attributes {
			attributes[k] = v
		}
	}
	// Ensure parameters aren't passed twice.
	if params.Name != "" {
		if _, exists := attributes["name"]; exists {
			return nil, errors.New("cannot set both FindParams.Name and FindParams.Attributes['name']")
		}
		attributes["name"] = params.Name
	}
	if params.ClassName != "" {
		if _, exists := attributes["className"]; exists {
			return nil, errors.New("cannot set both FindParams.ClassName and FindParams.Attributes['className']")
		}
		attributes["className"] = params.ClassName
	}

	// Return null if empty dictionary
	if len(attributes) == 0 {
		return []byte("null"), nil
	}

	// json.Marshal can't be used because this is JavaScript code with regular expressions, not JSON.
	// TODO(bhansknecht): work with chrome.automation API maintainers to support a JSON friendly regex format.
	var buf bytes.Buffer
	buf.WriteByte('{')
	first := true
	for k, v := range attributes {
		if first {
			first = false
		} else {
			buf.WriteByte(',')
		}
		switch v := v.(type) {
		case string, RoleType, CheckedState, RestrictionState:
			fmt.Fprintf(&buf, "%q:%q", k, v)
		case int, float32, float64, bool:
			fmt.Fprintf(&buf, "%q:%v", k, v)
		case regexp.Regexp, *regexp.Regexp:
			fmt.Fprintf(&buf, `%q:/%v/`, k, v)
		default:
			return nil, errors.Errorf("FindParams does not support type(%T) for parameter(%s)", v, k)
		}
	}
	buf.WriteByte('}')
	return buf.Bytes(), nil
}

// rawBytes converts FindParams into a JSON-like object that can contain JS Regexp Notation.
// The result will be return as a byte Array.
func (params *FindParams) rawBytes() ([]byte, error) {
	var buf bytes.Buffer
	buf.WriteByte('{')
	rawAttributes, err := params.rawAttributes()
	if err != nil {
		return nil, err
	}
	fmt.Fprintf(&buf, `"attributes":%s,`, rawAttributes)

	if params.Role != "" {
		fmt.Fprintf(&buf, `"role":%q,`, params.Role)
	}

	state, err := json.Marshal(params.State)
	if err != nil {
		return nil, err
	}
	fmt.Fprintf(&buf, `"state":%s`, state)

	buf.WriteByte('}')
	return buf.Bytes(), nil
}

// Node is a reference to chrome.automation API AutomationNode.
// Node intentionally leaves out many properties. If they become needed, add them to the Node struct and to the Update function.
// As defined in chromium/src/extensions/common/api/automation.idl
// Exported fields are sorted in alphabetical order.
type Node struct {
	object         *chrome.JSObject
	tconn          *chrome.TestConn
	Checked        CheckedState       `json:"checked,omitempty"`
	ClassName      string             `json:"className,omitempty"`
	HTMLAttributes map[string]string  `json:"htmlAttributes,omitempty"`
	Location       coords.Rect        `json:"location,omitempty"`
	Name           string             `json:"name,omitempty"`
	Restriction    RestrictionState   `json:"restriction,omitempty"`
	Role           RoleType           `json:"role,omitempty"`
	State          map[StateType]bool `json:"state,omitempty"`
	Value          string             `json:"value,omitempty"`
}

// NodeSlice is a slice of pointers to nodes. It is used for releaseing a group of nodes.
type NodeSlice []*Node

// Release frees the reference to Javascript for this node.
func (nodes NodeSlice) Release(ctx context.Context) {
	for _, n := range nodes {
		defer n.Release(ctx)
	}
}

// NewNode creates a new node struct and initializes its fields.
// NewNode takes ownership of obj and will release it if the node fails to initialize.
func NewNode(ctx context.Context, tconn *chrome.TestConn, obj *chrome.JSObject) (*Node, error) {
	node := &Node{
		object: obj,
		tconn:  tconn,
	}
	if err := node.Update(ctx); err != nil {
		node.Release(ctx)
		return nil, errors.Wrap(err, "failed to initialize node")
	}
	return node, nil
}

// Update reloads the fields of this node.
func (n *Node) Update(ctx context.Context) error {
	return n.object.Call(ctx, n, `function(){
		return {
			checked: this.checked,
			className: this.className,
			htmlAttributes: this.htmlAttributes,
			location: this.location,
			name: this.name,
			restriction: this.restriction,
			role: this.role,
			state: this.state,
			tooltip: this.tooltip,
			value: this.value,
			valueForRange: this.valueForRange,
		}
	}`)
}

// Release frees the reference to Javascript for this node.
func (n *Node) Release(ctx context.Context) {
	n.object.Release(ctx)
}

// LeftClick executes a left click on the node.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) LeftClick(ctx context.Context) error {
	return n.mouseClick(ctx, leftClick)
}

// RightClick executes a right click on the node.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) RightClick(ctx context.Context) error {
	return n.mouseClick(ctx, rightClick)
}

// DoubleClick executes 2 mouse left clicks on the node.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) DoubleClick(ctx context.Context) error {
	return n.mouseClick(ctx, doubleClick)
}

// StableLeftClick waits for the location to be stable and then left clicks the node.
// The location must be stable for 1 iteration of polling (default 100ms).
func (n *Node) StableLeftClick(ctx context.Context, pollOpts *testing.PollOptions) error {
	return n.stableMouseClick(ctx, leftClick, pollOpts)
}

// StableRightClick waits for the location to be stable and then right clicks the node.
// The location must be stable for 1 iteration of polling (default 100ms).
func (n *Node) StableRightClick(ctx context.Context, pollOpts *testing.PollOptions) error {
	return n.stableMouseClick(ctx, rightClick, pollOpts)
}

// StableDoubleClick waits for the location to be stable and then double clicks the node.
// The location must be stable for 1 iteration of polling (default 100ms).
func (n *Node) StableDoubleClick(ctx context.Context, pollOpts *testing.PollOptions) error {
	return n.stableMouseClick(ctx, doubleClick, pollOpts)
}

// clickType describes how user clicks mouse.
type clickType int

const (
	leftClick clickType = iota
	rightClick
	doubleClick
)

const clickNode = `
	async function(button){
		var loc = this.location;
		var centerpoint = {"x": loc.left + loc.width/2, "y": loc.top + loc.height/2};
		await tast.promisify(chrome.autotestPrivate.mouseMove)(centerpoint, 0);
		await tast.promisify(chrome.autotestPrivate.mouseClick)(button);
	}`

func (n *Node) mouseClick(ctx context.Context, ct clickType) error {
	switch ct {
	case leftClick:
		return n.object.Call(ctx, nil, clickNode, mouse.LeftButton)
	case rightClick:
		return n.object.Call(ctx, nil, clickNode, mouse.RightButton)
	case doubleClick:
		if err := n.Update(ctx); err != nil {
			return errors.Wrap(err, "failed to update the node's location")
		}
		if n.Location.Empty() {
			return errors.New("This node doesn't have a location on the screen and can't be clicked")
		}
		return mouse.DoubleClick(ctx, n.tconn, n.Location.CenterPoint(), 100*time.Millisecond)
	default:
		return errors.New("invalid click type")
	}
}

func (n *Node) updateLocation(ctx context.Context) error {
	return n.object.Call(ctx, &n.Location, `function(){return this.location}`)
}

// WaitLocationStable waits for the nodes location to be the same for a single iteration of polling.
// Polling options work the same way as in testing.Poll().
func (n *Node) WaitLocationStable(ctx context.Context, pollOpts *testing.PollOptions) error {
	location := coords.Rect{}
	if err := testing.Poll(ctx, func(ctx context.Context) error {
		if err := n.updateLocation(ctx); err != nil {
			return testing.PollBreak(errors.Wrap(err, "failed to update the node's location"))
		}
		if !cmp.Equal(n.Location, location) {
			location = n.Location
			return errors.New("node location still changing")
		}
		return nil
	}, pollOpts); err != nil {
		return errors.Wrap(err, "node location unstable")
	}
	return nil
}

// stableMouseClick waits for a nodes location to be stable before attempting to click it.
// The location must be stable for 1 iteration of polling (default 100ms).
func (n *Node) stableMouseClick(ctx context.Context, ct clickType, pollOpts *testing.PollOptions) error {
	if err := n.WaitLocationStable(ctx, pollOpts); err != nil {
		return err
	}
	return n.mouseClick(ctx, ct)
}

// LeftClickUntil repeatedly left clicks the node until the condition returns true with no error.
// This is useful for situations where there is no indication of whether the node is ready to receive clicks.
// The interval between clicks and the timeout can be specified using testing.PollOptions.
// todo(crbug/1099507): remove this function when we have a better indicator of clickability in general
func (n *Node) LeftClickUntil(ctx context.Context, condition func(context.Context) (bool, error), opts *testing.PollOptions) error {
	return testing.Poll(ctx, func(ctx context.Context) error {
		if result, err := condition(ctx); err != nil {
			return testing.PollBreak(err)
		} else if !result {
			if err := n.LeftClick(ctx); err != nil {
				return errors.Wrap(err, "failed to click node")
			}
			return errors.New("click may not have been received yet")
		}
		return nil
	}, opts)
}

// StableFind repeatedly finds the first matching node until the node's location if stable.
// It will relocate the node if unexpected error happens, such as an element being refreshed.
// Stable*Click and WaitLocationStable are alternative solutions if the node is not completely deleted and recreated.
// Side effect: using this function will increase the test duration.
// Error example: "Failed to update the node's location: unexpected end of JSON input".
// Error example: "Cannot read property 'left' of undefined".
func StableFind(ctx context.Context, tconn *chrome.TestConn, params FindParams, opts *testing.PollOptions) (node *Node, err error) {
	location := coords.Rect{}

	return node, testing.Poll(ctx, func(ctx context.Context) error {
		node, err = Find(ctx, tconn, params)
		if err != nil {
			return errors.Wrap(err, "failed to find node")
		}
		if !cmp.Equal(node.Location, location) {
			location = node.Location
			node.Release(ctx)
			return errors.New("node location still changing")
		}
		return nil
	}, opts)
}

// StableFindAndClick waits for the first matching stable node and then left clicks it.
func StableFindAndClick(ctx context.Context, tconn *chrome.TestConn, params FindParams, opts *testing.PollOptions) error {
	node, err := StableFind(ctx, tconn, params, opts)
	if err != nil {
		return errors.Wrapf(err, "failed to find stable node with %v", params)
	}
	defer node.Release(ctx)
	return node.LeftClick(ctx)
}

// StableFindAndRightClick waits for the first matching stable node and then right clicks it.
func StableFindAndRightClick(ctx context.Context, tconn *chrome.TestConn, params FindParams, opts *testing.PollOptions) error {
	node, err := StableFind(ctx, tconn, params, opts)
	if err != nil {
		return errors.Wrapf(err, "failed to find stable node with %v", params)
	}
	defer node.Release(ctx)
	return node.RightClick(ctx)
}

// FocusAndWait calls the focus() Javascript method of the AutomationNode.
// This can be used to scroll to nodes which aren't currently visible, enabling them to be clicked.
// The focus event is not instant, so an EventWatcher (watcher.go) is used to check its status.
// The EventWatcher waits the duration of timeout for the event to occur.
func (n *Node) FocusAndWait(ctx context.Context, timeout time.Duration) error {
	ew, err := NewWatcher(ctx, n, EventTypeFocus)
	if err != nil {
		return errors.Wrap(err, "failed to create focus event watcher")
	}
	defer ew.Release(ctx)

	if err := n.object.Call(ctx, nil, "function(){this.focus()}"); err != nil {
		return errors.Wrap(err, "failed to call focus() on the specified node")
	}

	if _, err := ew.WaitForEvent(ctx, timeout); err != nil {
		return errors.Wrap(err, "failed to wait for the focus event on the specified node")
	}

	return nil
}

// MakeVisible calls makeVisible() Javascript method of the AutomationNode to make
// target node visible.
func (n *Node) MakeVisible(ctx context.Context) error {
	if err := n.object.Call(ctx, nil, "function(){return this.makeVisible()}"); err != nil {
		return errors.Wrap(err, "failed to call makeVisible() on the specified node")
	}
	return nil
}

// Descendant finds the first descendant of this node matching the params and returns it.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) Descendant(ctx context.Context, params FindParams) (*Node, error) {
	paramsBytes, err := params.rawBytes()
	if err != nil {
		return nil, err
	}
	obj := &chrome.JSObject{}
	if err := n.object.Call(ctx, obj, fmt.Sprintf("function(){return this.find(%s)}", paramsBytes)); err != nil {
		return nil, err
	}
	return NewNode(ctx, n.tconn, obj)
}

// Descendants finds all descendant of this node matching the params and returns them.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) Descendants(ctx context.Context, params FindParams) (NodeSlice, error) {
	paramsBytes, err := params.rawBytes()
	if err != nil {
		return nil, err
	}
	nodeList := &chrome.JSObject{}
	if err := n.object.Call(ctx, nodeList, fmt.Sprintf("function(){return this.findAll(%s)}", paramsBytes)); err != nil {
		return nil, err
	}
	defer nodeList.Release(ctx)

	var len int
	if err := nodeList.Call(ctx, &len, "function(){return this.length}"); err != nil {
		return nil, err
	}

	var nodes NodeSlice
	for i := 0; i < len; i++ {
		node, err := func() (*Node, error) {
			obj := &chrome.JSObject{}
			if err := nodeList.Call(ctx, obj, "function(i){return this[i]}", i); err != nil {
				nodes.Release(ctx)
				return nil, err
			}
			return NewNode(ctx, n.tconn, obj)
		}()
		if err != nil {
			return nil, err
		}
		nodes = append(nodes, node)
	}
	return nodes, nil
}

// DescendantWithTimeout finds a descendant of this node using params and returns it.
// If the timeout is hit or the JavaScript fails to execute, an error is returned.
func (n *Node) DescendantWithTimeout(ctx context.Context, params FindParams, timeout time.Duration) (*Node, error) {
	if err := n.WaitUntilDescendantExists(ctx, params, timeout); err != nil {
		return nil, err
	}
	return n.Descendant(ctx, params)
}

// DescendantExists checks if a descendant of this node can be found.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) DescendantExists(ctx context.Context, params FindParams) (bool, error) {
	paramsBytes, err := params.rawBytes()
	if err != nil {
		return false, err
	}
	var exists bool
	if err = n.object.Call(ctx, &exists, fmt.Sprintf("function(){return !!(this.find(%s))}", paramsBytes)); err != nil {
		return false, err
	}
	return exists, nil
}

// ErrNodeDoesNotExist is returned when the node is not found.
var ErrNodeDoesNotExist = errors.New("node does not exist")

// WaitUntilDescendantExists checks if a descendant node exists repeatedly until the timeout.
// If the timeout is hit or the JavaScript fails to execute, an error is returned.
func (n *Node) WaitUntilDescendantExists(ctx context.Context, params FindParams, timeout time.Duration) error {
	return testing.Poll(ctx, func(ctx context.Context) error {
		exists, err := n.DescendantExists(ctx, params)
		if err != nil {
			return testing.PollBreak(err)
		}
		if !exists {
			return ErrNodeDoesNotExist
		}
		return nil
	}, &testing.PollOptions{Timeout: timeout})
}

// ErrNodeExists is returned when the node is found, but should not exist.
var ErrNodeExists = errors.New("node still exists")

// WaitUntilDescendantGone checks if a descendant node doesn't exist repeatedly until the timeout.
// If the timeout is hit or the JavaScript fails to execute, an error is returned.
func (n *Node) WaitUntilDescendantGone(ctx context.Context, params FindParams, timeout time.Duration) error {
	return testing.Poll(ctx, func(ctx context.Context) error {
		exists, err := n.DescendantExists(ctx, params)
		if err != nil {
			return testing.PollBreak(err)
		}
		if exists {
			return ErrNodeExists
		}
		return nil
	}, &testing.PollOptions{Timeout: timeout})
}

// Matches returns whether this node matches the given params.
func (n *Node) Matches(ctx context.Context, params FindParams) (bool, error) {
	paramsBytes, err := params.rawBytes()
	if err != nil {
		return false, err
	}
	var match bool
	if err := n.object.Call(ctx, &match, fmt.Sprintf("function(){return this.matches(%s)}", paramsBytes)); err != nil {
		return false, err
	}
	return match, nil
}

// Attribute gets the specified attribute of this node.
// This method is for odd/uncommon attributes. For common attributes, add them to the Node struct.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) Attribute(ctx context.Context, attributeName string) (interface{}, error) {
	var out interface{}

	if err := n.object.Call(ctx, &out, "function(attr){return this[attr]}", attributeName); err != nil {
		return nil, err
	}
	return out, nil
}

// Children returns the children of the node.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) Children(ctx context.Context) (NodeSlice, error) {
	childrenList := &chrome.JSObject{}
	if err := n.object.Call(ctx, childrenList, "function(){return this.children}"); err != nil {
		return nil, errors.Wrap(err, "failed to call children() on the specified node")
	}
	defer childrenList.Release(ctx)

	var numChildren int
	if err := childrenList.Call(ctx, &numChildren, "function(){return this.length}"); err != nil {
		return nil, err
	}

	var children NodeSlice
	for i := 0; i < numChildren; i++ {
		node, err := func() (*Node, error) {
			currChild := &chrome.JSObject{}
			if err := childrenList.Call(ctx, currChild, "function(i){return this[i]}", i); err != nil {
				return nil, err
			}
			return NewNode(ctx, n.tconn, currChild)
		}()
		if err != nil {
			children.Release(ctx)
			return nil, err
		}
		children = append(children, node)
	}
	return children, nil
}

// ToString returns string representation of node.
// If the JavaScript fails to execute, an error is returned.
func (n *Node) ToString(ctx context.Context) (string, error) {
	var nodeString string
	if err := n.object.Call(ctx, &nodeString, "function() {return this.toString()}"); err != nil {
		return "", err
	}
	return nodeString, nil
}

// Root returns the chrome.automation root as a Node.
// If the JavaScript fails to execute, an error is returned.
func Root(ctx context.Context, tconn *chrome.TestConn) (*Node, error) {
	obj := &chrome.JSObject{}
	if err := tconn.EvalPromise(ctx, "tast.promisify(chrome.automation.getDesktop)()", obj); err != nil {
		return nil, err
	}
	return NewNode(ctx, tconn, obj)
}

// Select sets the document selection to include everything between the two nodes at the offsets.
// If the JavaScript fails to execute, an error is returned.
func Select(ctx context.Context, startNode *Node, startOffset int, endNode *Node, endOffset int) error {
	return startNode.tconn.Call(ctx, nil, `function(anchorObject, anchorOffset, focusObject, focusOffset){
		chrome.automation.setDocumentSelection({anchorObject, anchorOffset, focusObject, focusOffset})
	}`, startNode.object, startOffset, endNode.object, endOffset)
}

// Find finds the first descendant of the root node matching the params and returns it.
// If the JavaScript fails to execute, an error is returned.
func Find(ctx context.Context, tconn *chrome.TestConn, params FindParams) (*Node, error) {
	root, err := Root(ctx, tconn)
	if err != nil {
		return nil, err
	}
	defer root.Release(ctx)
	return root.Descendant(ctx, params)
}

// FindAll finds all descendants of the root node matching the params and returns them.
// If the JavaScript fails to execute, an error is returned.
func FindAll(ctx context.Context, tconn *chrome.TestConn, params FindParams) (NodeSlice, error) {
	root, err := Root(ctx, tconn)
	if err != nil {
		return nil, err
	}
	defer root.Release(ctx)
	return root.Descendants(ctx, params)
}

// FindWithTimeout finds a descendant of the root node using params and returns it.
// If the JavaScript fails to execute, an error is returned.
func FindWithTimeout(ctx context.Context, tconn *chrome.TestConn, params FindParams, timeout time.Duration) (*Node, error) {
	root, err := Root(ctx, tconn)
	if err != nil {
		return nil, err
	}
	defer root.Release(ctx)
	return root.DescendantWithTimeout(ctx, params, timeout)
}

// Exists checks if a descendant of the root node can be found.
// If the JavaScript fails to execute, an error is returned.
func Exists(ctx context.Context, tconn *chrome.TestConn, params FindParams) (bool, error) {
	root, err := Root(ctx, tconn)
	if err != nil {
		return false, err
	}
	defer root.Release(ctx)
	return root.DescendantExists(ctx, params)
}

// WaitUntilExists checks if a node exists repeatedly until the timeout.
// If the JavaScript fails to execute, an error is returned.
func WaitUntilExists(ctx context.Context, tconn *chrome.TestConn, params FindParams, timeout time.Duration) error {
	root, err := Root(ctx, tconn)
	if err != nil {
		return err
	}
	defer root.Release(ctx)
	return root.WaitUntilDescendantExists(ctx, params, timeout)
}

// WaitUntilGone checks if a node doesn't exist repeatedly until the timeout.
// If the JavaScript fails to execute, an error is returned.
func WaitUntilGone(ctx context.Context, tconn *chrome.TestConn, params FindParams, timeout time.Duration) error {
	root, err := Root(ctx, tconn)
	if err != nil {
		return err
	}
	defer root.Release(ctx)
	return root.WaitUntilDescendantGone(ctx, params, timeout)
}

// WaitUntilExistsStatus repeatedly checks the existence of a node
// until the desired status is found or the timeout is reached.
// If the JavaScript fails to execute, an error is returned.
func WaitUntilExistsStatus(ctx context.Context, tconn *chrome.TestConn, params FindParams, exists bool, timeout time.Duration) error {
	if exists {
		return WaitUntilExists(ctx, tconn, params, timeout)
	}

	return WaitUntilGone(ctx, tconn, params, timeout)
}

// RootDebugInfo returns the chrome.automation root as a string.
// If the JavaScript fails to execute, an error is returned.
func RootDebugInfo(ctx context.Context, tconn *chrome.TestConn) (string, error) {
	var out string
	err := tconn.EvalPromise(ctx, "tast.promisify(chrome.automation.getDesktop)().then(root => root+'');", &out)
	return out, err
}

// LogRootDebugInfo logs the chrome.automation root debug info to a file.
func LogRootDebugInfo(ctx context.Context, tconn *chrome.TestConn, filename string) error {
	debugInfo, err := RootDebugInfo(ctx, tconn)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(filename, []byte(debugInfo), 0644)
}

// ErrNoRadioButtons is returned when there are no radio buttons under the radio group.
var ErrNoRadioButtons = errors.New("no radio buttons in this radio group")

// ErrNoActiveRadioButton is returned when no active radio group is selected.
var ErrNoActiveRadioButton = errors.New("no active radio button is selected")

// FindSelectedRadioButton finds the selected radio button under a radio group node.
// If no active radio button is selected, an error is returned.
func (n *Node) FindSelectedRadioButton(ctx context.Context) (*Node, error) {
	if n.Role != RoleTypeRadioGroup {
		return nil, errors.New("the current node is not a radio group")
	}

	if rbExists, err := n.DescendantExists(ctx, FindParams{Role: RoleTypeRadioButton}); err != nil {
		return nil, errors.Wrap(err, "failed to run javascript to check if radio buttons exist")
	} else if rbExists == false {
		return nil, ErrNoRadioButtons
	}

	if selectedExists, err := n.DescendantExists(ctx, FindParams{
		Role:       RoleTypeRadioButton,
		Attributes: map[string]interface{}{"checked": CheckedStateTrue},
	}); err != nil {
		return nil, errors.Wrap(err, "failed to run javascript to check if a selected radio button exist")
	} else if selectedExists == false {
		return nil, ErrNoActiveRadioButton
	}

	return n.Descendant(ctx, FindParams{
		Role:       RoleTypeRadioButton,
		Attributes: map[string]interface{}{"checked": CheckedStateTrue},
	})
}


text:
package mypod

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/dhowden/tag"
	"github.com/gabriel-vasile/mimetype"
	"github.com/jbub/podcasts"
	"github.com/technoweenie/grohl"
)

func NewFeedHandler(dir string, logger *grohl.Context) http.Handler {
	return &FeedHandler{
		dir:    dir,
		logger: logger,
	}
}

type FeedHandler struct {
	dir    string
	logger *grohl.Context
}

func (h *FeedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	feed, err := h.GetFeed()
	if err != nil {
		http.Error(w, "error generating feed: "+err.Error(), http.StatusInternalServerError)
		return
	}
	if err := feed.Write(w); err != nil {
		http.Error(w, "error writing feed: "+err.Error(), http.StatusInternalServerError)
		return
	}
}

func (h *FeedHandler) GetFeed() (*podcasts.Feed, error) {
	conf, err := ReadConfig(filepath.Join(h.dir, "podcast.json"))
	if err != nil {
		return nil, err
	}

	baseURL, err := url.Parse(conf.BaseURL)
	if err != nil {
		return nil, err
	}

	// initialize the podcast
	podcast := &podcasts.Podcast{
		Title:       conf.Title,
		Description: conf.Description,
		Language:    conf.Language,
		Link:        conf.Link,
		Copyright:   conf.Copyright,
	}

	// add items
	items, err := h.ReadPodcastEpisodes(conf)
	if err != nil {
		return nil, err
	}
	for _, item := range items {
		// Complete podcast episode URL
		itemPath := item.Enclosure.URL
		itemURL := &url.URL{
			Scheme: baseURL.Scheme,
			Opaque: baseURL.Opaque,
			User:   baseURL.User,
			Host:   baseURL.Host,
			Path:   "/files/" + itemPath,
		}
		item.Enclosure.URL = itemURL.String()

		// Complete podcast episode image URL
		imagePath := item.Image.Href
		imageURL := &url.URL{
			Scheme: baseURL.Scheme,
			Opaque: baseURL.Opaque,
			User:   baseURL.User,
			Host:   baseURL.Host,
			Path:   imagePath,
		}
		item.Image.Href = imageURL.String()

		podcast.AddItem(item)
	}

	imageURL := &url.URL{
		Scheme: baseURL.Scheme,
		Opaque: baseURL.Opaque,
		User:   baseURL.User,
		Host:   baseURL.Host,
		Path:   conf.Image,
	}

	// build feed
	return podcast.Feed(
		podcasts.Author(conf.Author),
		podcasts.NewFeedURL(conf.BaseURL+"/feed.xml"),
		podcasts.Subtitle(conf.Subtitle),
		podcasts.Summary(conf.Summary),
		podcasts.Owner(conf.Owner.Name, conf.Owner.Email),
		podcasts.Image(imageURL.String()),
		setCategories(conf),
		setExplicit(conf.Explicit),
	)
}

func setCategories(conf Config) func(f *podcasts.Feed) error {
	return func(f *podcasts.Feed) error {
		f.Channel.Categories = []*podcasts.ItunesCategory{}
		for _, category := range conf.Categories {
			f.Channel.Categories = append(f.Channel.Categories, &podcasts.ItunesCategory{
				Text: category,
			})
		}
		return nil
	}
}

func setExplicit(explicit bool) func(f *podcasts.Feed) error {
	return func(f *podcasts.Feed) error {
		if explicit {
			f.Channel.Explicit = podcasts.ValueYes
		} else {
			f.Channel.Explicit = "no"
		}
		return nil
	}
}

func (h *FeedHandler) ReadPodcastEpisodes(conf Config) ([]*podcasts.Item, error) {
	imagePaths, err := listImagePaths(h.dir + "/images")
	if err != nil {
		grohl.Log(grohl.Data{
			"msg":   "listing thumbnail images",
			"error": err.Error(),
		})
	}

	items := []*podcasts.Item{}
	walkErr := filepath.Walk(h.dir+"/files", func(filePath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		fileLocation, err := filepath.Rel(h.dir, filePath)
		if err != nil {
			return err
		}

		item := &podcasts.Item{
			Title:    titleize(fileLocation),
			PubDate:  podcasts.NewPubDate(info.ModTime()),
			GUID:     hash(filePath + info.ModTime().String()),
			Author:   conf.Author,
			Subtitle: "A subtitle for this episode",
			Summary:  &podcasts.ItunesSummary{Value: "A summary for this episode"},
			Enclosure: &podcasts.Enclosure{
				URL:    filepath.Base(fileLocation),
				Length: strconv.FormatInt(info.Size(), 10),
			},
			Explicit: "no",
		}

		if thumbnailPath := episodeThumbnailPath(imagePaths, filePath); thumbnailPath != "" {
			item.Image = &podcasts.ItunesImage{Href: thumbnailPath}
		} else {
			item.Image = &podcasts.ItunesImage{Href: conf.Image}
		}

		if mime, err := mimetype.DetectFile(filePath); err == nil {
			item.Enclosure.Type = mime.String()
		}

		if metadata, err := readMetadata(filePath); err == nil {
			if title := metadata.Title(); title != "" {
				item.Title = title
			}
			if author := metadata.Artist(); author != "" {
				item.Author = author
			}
			if comment := metadata.Comment(); comment != "" {
				item.Summary = &podcasts.ItunesSummary{Value: comment}
			}
		}

		if duration, err := readDuration(filePath); err == nil {
			item.Duration = podcasts.NewDuration(duration)
		}

		items = append(items, item)
		return nil
	})

	// Sort by pubDate DESC (newer first, older last).
	sort.SliceStable(items, func(i, j int) bool {
		return items[i].PubDate.Time.After(items[j].PubDate.Time)
	})

	return items, walkErr
}

func titleize(fileLocation string) string {
	title := fileLocation
	// Give me the base name
	title = filepath.Base(title)
	// Remove extension
	title = title[0 : len(title)-len(filepath.Ext(title))]
	// Replace underscores with spaces
	title = strings.Replace(title, "_", " ", -1)
	// Capitalize
	title = strings.Title(title)
	return title
}

func hash(str string) string {
	sum := sha256.Sum256([]byte(str))
	return hex.EncodeToString(sum[:])
}

func listImagePaths(imagesDir string) ([]string, error) {
	infos, err := ioutil.ReadDir(imagesDir)
	if err != nil {
		return []string{}, err
	}
	thumbnails := []string{}
	for _, info := range infos {
		if !info.IsDir() {
			thumbnails = append(thumbnails, info.Name())
		}
	}
	return thumbnails, nil
}

func episodeThumbnailPath(imagePaths []string, filePath string) string {
	// Try the exact episode name
	episodeName := filepath.Base(filePath)
	episodeName = episodeName[0 : len(episodeName)-len(filepath.Ext(episodeName))]

	for _, thumbnailFileName := range imagePaths {
		if strings.HasPrefix(thumbnailFileName, episodeName) {
			return "/images/" + thumbnailFileName
		}
	}

	// Try removing the video key
	if idx := strings.LastIndex(episodeName, "-"); idx > 0 {
		episodeName = episodeName[0:idx]
		for _, thumbnailFileName := range imagePaths {
			if strings.HasPrefix(thumbnailFileName, episodeName) {
				return "/images/" + thumbnailFileName
			}
		}
	}

	return ""
}

func readMetadata(filePath string) (tag.Metadata, error) {
	f, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	return tag.ReadFrom(f)
}

func readDuration(filePath string) (time.Duration, error) {
	var buf bytes.Buffer
	cmd := exec.Command("ffprobe", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", "-i", filePath)
	cmd.Stdout = &buf
	cmd.Stderr = nil
	err := cmd.Run()
	if err != nil {
		return 0, err
	}
	// ffprobe responds with the total number of seconds.
	// itunes:duration should be in HH:MM:SS format, but since the library
	// requires a time.Duration, the best we can do is list the duration in seconds.
	// When the XML marshaling process occurs, we want to see the raw seconds value,
	// so we thus return the highest precision value we can for Duration, namely ns.
	return time.ParseDuration(strings.TrimSpace(buf.String()) + "ns")
}

license: MIT

repository: parkr/mypod

license_type: permissive

repo_name: parkr/mypod

branch_name: refs/heads/main

gha_license_id: MIT

gha_language: Go

extension: go


text:
#include <queue>
#include <cstdio>
#include <cstring>
#define MAXN 1010
using namespace std;

int g[MAXN][MAXN];
int n, x[MAXN][MAXN], y[MAXN][MAXN];
int sx, sy, tx, ty;
int dis[MAXN * MAXN];
bool vis[MAXN * MAXN];
queue <pair<int, int> > q;

inline int mymin(int a, int b)
{
	return a < b ? a : b;
}
inline void read(int &x)
{
	x = 0;
	char ch = getchar();
	while (ch < '0' || ch > '9') ch = getchar();
	while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return ;
}

inline void bfs()
{
	q.push(make_pair(sx, sy));
	dis[(sx - 1)*n + sy] = 0;
	while (!q.empty())
	{
		pair<int, int> u = q.front();
		q.pop();
		int xx = u.first, yy = u.second;
		if (xx == tx && yy == ty) return ;
		for (int i = 1; i <= x[xx][0]; i++)
		{
			if (x[xx][i] > yy)
			{
				int ty = x[xx][i] - 1;
				if (dis[(xx - 1)*n + ty] > dis[(xx - 1)*n + yy] + 1)
				{
					dis[(xx - 1)*n + ty] = dis[(xx - 1) * n + yy] + 1;
					q.push(make_pair(xx, ty));
				}
				break;
			}
		}
		for (int i = x[xx][0]; i; i--)
		{
			if (x[xx][i] < yy)
			{
				int ty = x[xx][i] + 1;
				if (dis[(xx - 1)*n + ty] > dis[(xx - 1)*n + yy] + 1)
				{
					dis[(xx - 1)*n + ty] = dis[(xx - 1) * n + yy] + 1;
					q.push(make_pair(xx, ty));
				}
				break;
			}
		}
		for (int i = 1; i <= y[yy][0]; i++)
		{
			if (y[yy][i] > xx)
			{
				int tx = y[yy][i] - 1;
				if (dis[(tx - 1)*n + yy] > dis[(xx - 1)*n + yy] + 1)
				{
					dis[(tx - 1)*n + yy] = dis[(xx - 1) * n + yy] + 1;
					q.push(make_pair(tx, yy));
				}
				break;
			}
		}
		for (int i = y[yy][0]; i; i--)
		{
			if (y[yy][i] < xx)
			{
				int tx = y[yy][i] + 1;
				if (dis[(tx - 1)*n + yy] > dis[(xx - 1)*n + yy] + 1)
				{
					dis[(tx - 1)*n + yy] = dis[(xx - 1) * n + yy] + 1;
					q.push(make_pair(tx, yy));
				}
				break;
			}
		}
	}
}

int main()
{
	memset(dis, 0x7f, sizeof dis);
	read(n);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			read(g[i][j]);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) if (g[i][j]) x[i][++x[i][0]] = j;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) if (g[j][i]) y[i][++y[i][0]] = j;
	read(sx);
	read(sy);
	read(tx);
	read(ty);
	bfs();
	if (dis[(tx - 1)*n + ty] == 0x7f7f7f7f) puts("impossible");
	else printf("%d\n", dis[(tx - 1)*n + ty]);
	return 0;
}

repository: HeRaNO/OI-ICPC-Codes

repo_name: HeRaNO/OI-ICPC-Codes

branch_name: refs/heads/master

extension: cpp


text:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE eagle SYSTEM "eagle.dtd">
<eagle version="9.5.1">
<drawing>
<settings>
<setting alwaysvectorfont="no"/>
<setting keepoldvectorfont="yes"/>
<setting verticaltext="up"/>
</settings>
<grid distance="25" unitdist="mil" unit="mil" style="dots" multiple="1" display="yes" altdistance="5" altunitdist="mil" altunit="mil"/>
<layers>
<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>
<layer number="2" name="Route2" color="16" fill="1" visible="no" active="no"/>
<layer number="3" name="Route3" color="17" fill="1" visible="no" active="no"/>
<layer number="4" name="Route4" color="18" fill="1" visible="no" active="no"/>
<layer number="5" name="Route5" color="19" fill="1" visible="no" active="no"/>
<layer number="6" name="Route6" color="25" fill="1" visible="no" active="no"/>
<layer number="7" name="Route7" color="26" fill="1" visible="no" active="no"/>
<layer number="8" name="Route8" color="27" fill="1" visible="no" active="no"/>
<layer number="9" name="Route9" color="28" fill="1" visible="no" active="no"/>
<layer number="10" name="Route10" color="29" fill="1" visible="no" active="no"/>
<layer number="11" name="Route11" color="30" fill="1" visible="no" active="no"/>
<layer number="12" name="Route12" color="20" fill="1" visible="no" active="no"/>
<layer number="13" name="Route13" color="21" fill="1" visible="no" active="no"/>
<layer number="14" name="Route14" color="22" fill="1" visible="no" active="no"/>
<layer number="15" name="Route15" color="23" fill="1" visible="no" active="no"/>
<layer number="16" name="Bottom" color="1" fill="1" visible="yes" active="yes"/>
<layer number="17" name="Pads" color="2" fill="1" visible="yes" active="yes"/>
<layer number="18" name="Vias" color="2" fill="1" visible="yes" active="yes"/>
<layer number="19" name="Unrouted" color="6" fill="1" visible="yes" active="yes"/>
<layer number="20" name="Dimension" color="24" fill="1" visible="yes" active="yes"/>
<layer number="21" name="tPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="22" name="bPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="23" name="tOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="24" name="bOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="25" name="tNames" color="7" fill="1" visible="no" active="yes"/>
<layer number="26" name="bNames" color="7" fill="1" visible="no" active="yes"/>
<layer number="27" name="tValues" color="7" fill="1" visible="no" active="yes"/>
<layer number="28" name="bValues" color="7" fill="1" visible="no" active="yes"/>
<layer number="29" name="tStop" color="7" fill="3" visible="no" active="yes"/>
<layer number="30" name="bStop" color="7" fill="6" visible="no" active="yes"/>
<layer number="31" name="tCream" color="7" fill="4" visible="no" active="yes"/>
<layer number="32" name="bCream" color="7" fill="5" visible="no" active="yes"/>
<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="yes"/>
<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="yes"/>
<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="yes"/>
<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="yes"/>
<layer number="37" name="tTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="38" name="bTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="39" name="tKeepout" color="4" fill="11" visible="no" active="yes"/>
<layer number="40" name="bKeepout" color="1" fill="11" visible="no" active="yes"/>
<layer number="41" name="tRestrict" color="4" fill="10" visible="no" active="yes"/>
<layer number="42" name="bRestrict" color="1" fill="10" visible="no" active="yes"/>
<layer number="43" name="vRestrict" color="2" fill="10" visible="no" active="yes"/>
<layer number="44" name="Drills" color="7" fill="1" visible="no" active="yes"/>
<layer number="45" name="Holes" color="7" fill="1" visible="no" active="yes"/>
<layer number="46" name="Milling" color="3" fill="1" visible="no" active="yes"/>
<layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/>
<layer number="48" name="Document" color="7" fill="1" visible="no" active="yes"/>
<layer number="49" name="Reference" color="7" fill="1" visible="no" active="yes"/>
<layer number="50" name="dxf" color="7" fill="1" visible="no" active="no"/>
<layer number="51" name="tDocu" color="7" fill="1" visible="no" active="yes"/>
<layer number="52" name="bDocu" color="7" fill="1" visible="no" active="yes"/>
<layer number="53" name="tGND_GNDA" color="7" fill="9" visible="no" active="no"/>
<layer number="54" name="bGND_GNDA" color="1" fill="9" visible="no" active="no"/>
<layer number="56" name="wert" color="7" fill="1" visible="no" active="no"/>
<layer number="57" name="tCAD" color="7" fill="1" visible="no" active="no"/>
<layer number="59" name="tCarbon" color="7" fill="1" visible="no" active="no"/>
<layer number="60" name="bCarbon" color="7" fill="1" visible="no" active="no"/>
<layer number="88" name="SimResults" color="9" fill="1" visible="no" active="no"/>
<layer number="89" name="SimProbes" color="9" fill="1" visible="no" active="no"/>
<layer number="90" name="Modules" color="5" fill="1" visible="no" active="no"/>
<layer number="91" name="Nets" color="2" fill="1" visible="no" active="no"/>
<layer number="92" name="Busses" color="1" fill="1" visible="no" active="no"/>
<layer number="93" name="Pins" color="2" fill="1" visible="no" active="no"/>
<layer number="94" name="Symbols" color="4" fill="1" visible="no" active="no"/>
<layer number="95" name="Names" color="7" fill="1" visible="no" active="no"/>
<layer number="96" name="Values" color="7" fill="1" visible="no" active="no"/>
<layer number="97" name="Info" color="7" fill="1" visible="no" active="no"/>
<layer number="98" name="Guide" color="6" fill="1" visible="no" active="no"/>
<layer number="99" name="SpiceOrder" color="7" fill="1" visible="no" active="no"/>
<layer number="100" name="Muster" color="7" fill="1" visible="no" active="no"/>
<layer number="101" name="Patch_Top" color="12" fill="4" visible="no" active="yes"/>
<layer number="102" name="Vscore" color="7" fill="1" visible="no" active="yes"/>
<layer number="103" name="tMap" color="7" fill="1" visible="no" active="yes"/>
<layer number="104" name="Name" color="16" fill="1" visible="no" active="yes"/>
<layer number="105" name="tPlate" color="7" fill="1" visible="no" active="yes"/>
<layer number="106" name="bPlate" color="7" fill="1" visible="no" active="yes"/>
<layer number="107" name="Crop" color="7" fill="1" visible="no" active="yes"/>
<layer number="108" name="fp8" color="7" fill="1" visible="no" active="yes"/>
<layer number="109" name="fp9" color="7" fill="1" visible="no" active="yes"/>
<layer number="110" name="110" color="7" fill="1" visible="no" active="yes"/>
<layer number="111" name="111" color="7" fill="1" visible="no" active="yes"/>
<layer number="112" name="tSilk" color="7" fill="1" visible="no" active="yes"/>
<layer number="113" name="ReferenceLS" color="7" fill="1" visible="no" active="yes"/>
<layer number="116" name="Patch_BOT" color="9" fill="4" visible="no" active="yes"/>
<layer number="118" name="Rect_Pads" color="7" fill="1" visible="no" active="yes"/>
<layer number="121" name="_tsilk" color="7" fill="1" visible="no" active="yes"/>
<layer number="122" name="_bsilk" color="7" fill="1" visible="no" active="yes"/>
<layer number="123" name="tTestmark" color="7" fill="1" visible="no" active="yes"/>
<layer number="124" name="bTestmark" color="7" fill="1" visible="no" active="yes"/>
<layer number="125" name="_tNames" color="7" fill="1" visible="no" active="yes"/>
<layer number="126" name="_bNames" color="7" fill="1" visible="no" active="yes"/>
<layer number="127" name="_tValues" color="7" fill="1" visible="no" active="yes"/>
<layer number="128" name="_bValues" color="7" fill="1" visible="no" active="yes"/>
<layer number="129" name="Mask" color="7" fill="1" visible="no" active="yes"/>
<layer number="131" name="tAdjust" color="7" fill="1" visible="no" active="yes"/>
<layer number="132" name="bAdjust" color="7" fill="1" visible="no" active="yes"/>
<layer number="133" name="Ports" color="7" fill="1" visible="no" active="yes"/>
<layer number="134" name="Port2" color="7" fill="1" visible="no" active="yes"/>
<layer number="135" name="Port3" color="7" fill="1" visible="no" active="yes"/>
<layer number="144" name="Drill_legend" color="7" fill="1" visible="no" active="yes"/>
<layer number="150" name="Notes" color="7" fill="1" visible="no" active="yes"/>
<layer number="151" name="HeatSink" color="7" fill="1" visible="no" active="yes"/>
<layer number="152" name="_bDocu" color="7" fill="1" visible="no" active="yes"/>
<layer number="153" name="FabDoc1" color="7" fill="1" visible="no" active="yes"/>
<layer number="154" name="FabDoc2" color="7" fill="1" visible="no" active="yes"/>
<layer number="155" name="FabDoc3" color="7" fill="1" visible="no" active="yes"/>
<layer number="199" name="Contour" color="7" fill="1" visible="no" active="yes"/>
<layer number="200" name="200bmp" color="1" fill="10" visible="no" active="yes"/>
<layer number="201" name="201bmp" color="2" fill="10" visible="no" active="yes"/>
<layer number="202" name="202bmp" color="3" fill="10" visible="no" active="yes"/>
<layer number="203" name="203bmp" color="4" fill="10" visible="no" active="yes"/>
<layer number="204" name="204bmp" color="5" fill="10" visible="no" active="yes"/>
<layer number="205" name="205bmp" color="6" fill="10" visible="no" active="yes"/>
<layer number="206" name="206bmp" color="7" fill="10" visible="no" active="yes"/>
<layer number="207" name="207bmp" color="8" fill="10" visible="no" active="yes"/>
<layer number="208" name="208bmp" color="9" fill="10" visible="no" active="yes"/>
<layer number="209" name="209bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="210" name="210bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="211" name="211bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="212" name="212bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="213" name="213bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="214" name="214bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="215" name="215bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="216" name="216bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="217" name="217bmp" color="18" fill="1" visible="no" active="no"/>
<layer number="218" name="218bmp" color="19" fill="1" visible="no" active="no"/>
<layer number="219" name="219bmp" color="20" fill="1" visible="no" active="no"/>
<layer number="220" name="220bmp" color="21" fill="1" visible="no" active="no"/>
<layer number="221" name="221bmp" color="22" fill="1" visible="no" active="no"/>
<layer number="222" name="222bmp" color="23" fill="1" visible="no" active="no"/>
<layer number="223" name="223bmp" color="24" fill="1" visible="no" active="no"/>
<layer number="224" name="224bmp" color="25" fill="1" visible="no" active="no"/>
<layer number="225" name="225bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="226" name="topsilk" color="7" fill="1" visible="no" active="yes"/>
<layer number="227" name="227bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="228" name="228bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="229" name="229bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="230" name="230bmp" color="7" fill="1" visible="no" active="yes"/>
<layer number="231" name="Eagle3D_PG1" color="7" fill="1" visible="no" active="yes"/>
<layer number="232" name="Eagle3D_PG2" color="7" fill="1" visible="no" active="yes"/>
<layer number="233" name="Eagle3D_PG3" color="7" fill="1" visible="no" active="yes"/>
<layer number="248" name="Housing" color="7" fill="1" visible="no" active="yes"/>
<layer number="249" name="Edge" color="7" fill="1" visible="no" active="yes"/>
<layer number="250" name="Descript" color="3" fill="1" visible="no" active="no"/>
<layer number="251" name="SMDround" color="12" fill="11" visible="no" active="no"/>
<layer number="254" name="Paneldesc" color="14" fill="1" visible="no" active="yes"/>
<layer number="255" name="Panel" color="14" fill="1" visible="yes" active="yes"/>
</layers>
<board>
<plain>
<text x="25.4" y="95.25" size="1.778" layer="27"><9v 12v></text>
</plain>
<libraries>
<library name="OPL">
<packages>
<package name="C0603">
<description><b>0603<b><p></description>
<wire x1="-1.397" y1="0.635" x2="1.397" y2="0.635" width="0.127" layer="21"/>
<wire x1="1.397" y1="0.635" x2="1.397" y2="-0.635" width="0.127" layer="21"/>
<wire x1="1.397" y1="-0.635" x2="-1.397" y2="-0.635" width="0.127" layer="21"/>
<wire x1="-1.397" y1="-0.635" x2="-1.397" y2="0.635" width="0.127" layer="21"/>
<smd name="1" x="-0.762" y="0" dx="0.889" dy="0.889" layer="1" roundness="25" cream="no"/>
<smd name="2" x="0.762" y="0" dx="0.889" dy="0.889" layer="1" roundness="25" cream="no"/>
<text x="0" y="0" size="0.508" layer="25" ratio="11" align="center">>NAME</text>
<text x="0" y="-0.9525" size="0.508" layer="27" ratio="10" align="top-center">>VALUE</text>
<rectangle x1="-1.397" y1="-0.635" x2="1.397" y2="0.635" layer="39"/>
<polygon width="0.1" layer="31">
<vertex x="-1.0922" y="0.3302"/>
<vertex x="-1.0922" y="-0.3302"/>
<vertex x="-0.508" y="-0.3302"/>
<vertex x="-0.4318" y="0"/>
<vertex x="-0.508" y="0.3302"/>
</polygon>
<polygon width="0.1" layer="31">
<vertex x="1.0922" y="-0.3302"/>
<vertex x="1.0922" y="0.3302"/>
<vertex x="0.508" y="0.3302"/>
<vertex x="0.4318" y="0"/>
<vertex x="0.508" y="-0.3302"/>
</polygon>
</package>
<package name="DO-214AC">
<wire x1="2.2" y1="-1.3" x2="-2.2" y2="-1.3" width="0.127" layer="51"/>
<wire x1="-2.2" y1="-1.3" x2="-2.2" y2="1.3" width="0.127" layer="51"/>
<wire x1="-2.2" y1="1.3" x2="2.2" y2="1.3" width="0.127" layer="51"/>
<wire x1="2.2" y1="1.3" x2="2.2" y2="-1.3" width="0.127" layer="51"/>
<smd name="2" x="2" y="0" dx="1.7" dy="2.5" layer="1" rot="R270"/>
<smd name="1" x="-2" y="0" dx="1.7" dy="2.5" layer="1" rot="R270"/>
<text x="0" y="0" size="0.762" layer="25" ratio="11" align="center">>NAME</text>
<text x="-1.905" y="0" size="0.635" layer="27" ratio="10">>VALUE</text>
<rectangle x1="1.27" y1="-1.27" x2="1.651" y2="1.27" layer="51" rot="R180"/>
<polygon width="0.127" layer="21">
<vertex x="-0.381" y="-0.635"/>
<vertex x="-0.381" y="0.635"/>
<vertex x="0.381" y="0"/>
</polygon>
<wire x1="-3.5" y1="1" x2="3.5" y2="1" width="0.127" layer="21"/>
<wire x1="3.5" y1="1" x2="3.5" y2="-1" width="0.127" layer="21"/>
<wire x1="3.5" y1="-1" x2="-3.5" y2="-1" width="0.127" layer="21"/>
<wire x1="-3.5" y1="-1" x2="-3.5" y2="1" width="0.127" layer="21"/>
<rectangle x1="-3.429" y1="-1.397" x2="3.429" y2="1.397" layer="39"/>
<rectangle x1="0.5" y1="-1" x2="3.5" y2="1" layer="21"/>
</package>
<package name="R0603">
<wire x1="-1.397" y1="0.635" x2="1.397" y2="0.635" width="0.127" layer="21"/>
<wire x1="1.397" y1="0.635" x2="1.397" y2="-0.635" width="0.127" layer="21"/>
<wire x1="1.397" y1="-0.635" x2="-1.397" y2="-0.635" width="0.127" layer="21"/>
<wire x1="-1.397" y1="-0.635" x2="-1.397" y2="0.635" width="0.127" layer="21"/>
<smd name="1" x="-0.762" y="0" dx="0.889" dy="0.889" layer="1" roundness="25" cream="no"/>
<smd name="2" x="0.762" y="0" dx="0.889" dy="0.889" layer="1" roundness="25" cream="no"/>
<text x="0" y="0" size="0.508" layer="25" ratio="11" align="center">>NAME</text>
<text x="-1.397" y="-1.3175" size="0.508" layer="27" ratio="10">>VALUE</text>
<rectangle x1="-1.397" y1="-0.635" x2="1.397" y2="0.635" layer="39"/>
<polygon width="0.1" layer="31">
<vertex x="-1.0922" y="0.3302"/>
<vertex x="-1.0922" y="-0.3302"/>
<vertex x="-0.762" y="-0.3302"/>
<vertex x="-0.4318" y="0"/>
<vertex x="-0.762" y="0.3302"/>
</polygon>
<polygon width="0.1" layer="31">
<vertex x="1.0922" y="-0.3302"/>
<vertex x="1.0922" y="0.3302"/>
<vertex x="0.762" y="0.3302"/>
<vertex x="0.4318" y="0"/>
<vertex x="0.762" y="-0.3302"/>
</polygon>
</package>
</packages>
</library>
<library name="EurorackModularParts">
<packages>
<package name="CASE-A_3216">
<wire x1="-2.0955" y1="0.8255" x2="2.0955" y2="0.8255" width="0.127" layer="21"/>
<wire x1="2.0955" y1="0.8255" x2="2.0955" y2="-0.8255" width="0.127" layer="21"/>
<wire x1="2.0955" y1="-0.8255" x2="-2.0955" y2="-0.8255" width="0.127" layer="21"/>
<wire x1="-2.06375" y1="0.79375" x2="-3.4925" y2="0.79375" width="0.127" layer="21"/>
<wire x1="-3.4925" y1="0.79375" x2="-3.4925" y2="-0.79375" width="0.127" layer="21"/>
<wire x1="-3.4925" y1="-0.79375" x2="-2.06375" y2="-0.79375" width="0.127" layer="21"/>
<rectangle x1="-2.0955" y1="-0.8255" x2="2.0955" y2="0.8255" layer="39"/>
<smd name="+" x="-1.27" y="0" dx="1.27" dy="1.27" layer="1"/>
<smd name="-" x="1.27" y="0" dx="1.27" dy="1.27" layer="1" rot="R180"/>
<text x="-1.6" y="-1.492" size="0.635" layer="27" ratio="10">>VALUE</text>
<polygon width="0.127" layer="21">
<vertex x="-3.01625" y="0.79375"/>
<vertex x="-3.4925" y="0.79375"/>
<vertex x="-3.4925" y="0.3175"/>
<vertex x="-3.01625" y="0.3175"/>
</polygon>
<polygon width="0.127" layer="21">
<vertex x="-3.01625" y="-0.79375"/>
<vertex x="-3.01625" y="-0.3175"/>
<vertex x="-3.4925" y="-0.3175"/>
<vertex x="-3.4925" y="-0.79375"/>
</polygon>
<polygon width="0.127" layer="21">
<vertex x="-2.38125" y="-0.79375"/>
<vertex x="-2.38125" y="-0.3175"/>
<vertex x="-2.06375" y="-0.3175"/>
<vertex x="-2.06375" y="-0.79375"/>
</polygon>
<polygon width="0.127" layer="21">
<vertex x="-2.38125" y="0.79375"/>
<vertex x="-2.38125" y="0.3175"/>
<vertex x="-2.06375" y="0.3175"/>
<vertex x="-2.06375" y="0.79375"/>
</polygon>
<text x="0" y="0" size="0.762" layer="25" ratio="10" rot="SR0" align="center">>NAME</text>
</package>
<package name="ALPS_POT_SQUAREHOLES">
<circle x="0" y="0" radius="2.54" width="0.2032" layer="51"/>
<wire x1="-4.295" y1="5.46" x2="4.295" y2="5.46" width="0.127" layer="51"/>
<wire x1="4.295" y1="5.46" x2="4.295" y2="-4.33" width="0.127" layer="51"/>
<wire x1="4.295" y1="-4.33" x2="-4.295" y2="-4.33" width="0.127" layer="51"/>
<wire x1="-4.295" y1="-4.33" x2="-4.295" y2="5.46" width="0.127" layer="51"/>
<wire x1="1.1" y1="-0.625" x2="-1.1" y2="-0.625" width="0.2032" layer="51" curve="239.208901"/>
<wire x1="2.45" y1="-0.625" x2="-2.425" y2="-0.625" width="0.2032" layer="51"/>
<pad name="P$1" x="-2.5" y="-7.5" drill="1" rot="R90"/>
<pad name="P$2" x="0" y="-7.5" drill="1" rot="R90"/>
<pad name="P$3" x="2.58" y="-7.5" drill="1" rot="R90"/>
<text x="0" y="-1.905" size="1.27" layer="27" align="top-center">>VALUE</text>
<circle x="0" y="0" radius="4.75" width="0.002540625" layer="255"/>
<text x="0" y="7.62" size="1.778" layer="254" align="bottom-center">>DESC</text>
<rectangle x1="-2" y1="4" x2="2" y2="6" layer="41"/>
<rectangle x1="-2" y1="4" x2="2" y2="6" layer="21"/>
<text x="0" y="0" size="2.032" layer="25" ratio="10" rot="SR0" align="center">>NAME</text>
<text x="0" y="-2.54" size="1.27" layer="21" ratio="10" align="center">>VALUE</text>
<circle x="0" y="0" radius="6.5" width="0.127" layer="51"/>
<wire x1="-5.65" y1="-0.7" x2="-5.65" y2="0.7" width="0" layer="46"/>
<wire x1="-5.65" y1="0.7" x2="-3.85" y2="0.7" width="0" layer="46"/>
<wire x1="-3.85" y1="0.7" x2="-3.85" y2="-0.7" width="0" layer="46"/>
<wire x1="-3.85" y1="-0.7" x2="-5.65" y2="-0.7" width="0" layer="46"/>
<wire x1="3.85" y1="-0.7" x2="3.85" y2="0.7" width="0" layer="46"/>
<wire x1="3.85" y1="0.7" x2="5.65" y2="0.7" width="0" layer="46"/>
<wire x1="5.65" y1="0.7" x2="5.65" y2="-0.7" width="0" layer="46"/>
<wire x1="5.65" y1="-0.7" x2="3.85" y2="-0.7" width="0" layer="46"/>
<smd name="P$4" x="-4.75" y="0" dx="2.5" dy="2" layer="1" cream="no"/>
<smd name="P$5" x="4.75" y="0" dx="2.5" dy="2" layer="1" cream="no"/>
<smd name="P$6" x="-4.75" y="0" dx="2.5" dy="2" layer="16" cream="no"/>
<smd name="P$7" x="4.75" y="0" dx="2.5" dy="2" layer="16" cream="no"/>
<text x="0" y="2.032" size="1.016" layer="21" rot="R180" align="center">>DESC</text>
</package>
<package name="TSSOP14">
<wire x1="-2.1896" y1="-2.2828" x2="2.1896" y2="-2.2828" width="0.1524" layer="21"/>
<wire x1="2.1896" y1="2.2828" x2="2.1896" y2="-2.2828" width="0.1524" layer="21"/>
<wire x1="2.1896" y1="2.2828" x2="-2.1896" y2="2.2828" width="0.1524" layer="21"/>
<wire x1="-2.1896" y1="-2.2828" x2="-2.1896" y2="2.2828" width="0.1524" layer="21"/>
<wire x1="-1.961" y1="-2.0542" x2="1.961" y2="-2.0542" width="0.0508" layer="21"/>
<wire x1="1.961" y1="2.0542" x2="1.961" y2="-2.0542" width="0.0508" layer="21"/>
<wire x1="1.961" y1="2.0542" x2="-1.961" y2="2.0542" width="0.0508" layer="21"/>
<wire x1="-1.961" y1="-2.0542" x2="-1.961" y2="2.0542" width="0.0508" layer="21"/>
<smd name="1" x="-1.95" y="-2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="2" x="-1.3" y="-2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="3" x="-0.65" y="-2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="4" x="0" y="-2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="5" x="0.65" y="-2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="6" x="1.3" y="-2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="7" x="1.95" y="-2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="8" x="1.95" y="2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="9" x="1.3" y="2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="10" x="0.65" y="2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="11" x="0" y="2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="12" x="-0.65" y="2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="13" x="-1.3" y="2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<smd name="14" x="-1.95" y="2.9178" dx="0.3048" dy="0.9906" layer="1"/>
<text x="-2.6" y="0" size="1.016" layer="25" ratio="10" rot="R90" align="bottom-center">>NAME</text>
<text x="2.6" y="0" size="1.016" layer="27" ratio="10" rot="R90" align="top-center">>VALUE</text>
<rectangle x1="-2.0516" y1="-3.121" x2="-1.8484" y2="-2.2828" layer="51"/>
<rectangle x1="-1.4016" y1="-3.121" x2="-1.1984" y2="-2.2828" layer="51"/>
<rectangle x1="-0.7516" y1="-3.121" x2="-0.5484" y2="-2.2828" layer="51"/>
<rectangle x1="-0.1016" y1="-3.121" x2="0.1016" y2="-2.2828" layer="51"/>
<rectangle x1="0.5484" y1="-3.121" x2="0.7516" y2="-2.2828" layer="51"/>
<rectangle x1="1.1984" y1="-3.121" x2="1.4016" y2="-2.2828" layer="51"/>
<rectangle x1="1.8484" y1="-3.121" x2="2.0516" y2="-2.2828" layer="51"/>
<rectangle x1="1.8484" y1="2.2828" x2="2.0516" y2="3.121" layer="51"/>
<rectangle x1="1.1984" y1="2.2828" x2="1.4016" y2="3.121" layer="51"/>
<rectangle x1="0.5484" y1="2.2828" x2="0.7516" y2="3.121" layer="51"/>
<rectangle x1="-0.1016" y1="2.2828" x2="0.1016" y2="3.121" layer="51"/>
<rectangle x1="-0.7516" y1="2.2828" x2="-0.5484" y2="3.121" layer="51"/>
<rectangle x1="-1.4016" y1="2.2828" x2="-1.1984" y2="3.121" layer="51"/>
<rectangle x1="-2.0516" y1="2.2828" x2="-1.8484" y2="3.121" layer="51"/>
<wire x1="-2.275" y1="2.275" x2="-2.275" y2="-2.275" width="0.127" layer="21"/>
<wire x1="-2.275" y1="-2.275" x2="-2.275" y2="-3.575" width="0.127" layer="21"/>
<wire x1="-2.275" y1="-3.575" x2="-2.275" y2="-4.225" width="0.127" layer="21"/>
<wire x1="-2.275" y1="-4.225" x2="-1.625" y2="-4.225" width="0.127" layer="21"/>
<wire x1="-1.625" y1="-4.225" x2="-0.975" y2="-4.225" width="0.127" layer="21"/>
<wire x1="-0.975" y1="-4.225" x2="-0.975" y2="-3.575" width="0.127" layer="21"/>
<wire x1="-0.975" y1="-3.575" x2="-0.975" y2="-2.275" width="0.127" layer="21"/>
<wire x1="-2.275" y1="2.275" x2="2.275" y2="2.275" width="0.127" layer="21"/>
<wire x1="2.275" y1="2.275" x2="2.275" y2="-2.275" width="0.127" layer="21"/>
<wire x1="2.275" y1="-2.275" x2="-1.625" y2="-2.275" width="0.127" layer="21"/>
<wire x1="-1.625" y1="-2.275" x2="-2.275" y2="-2.275" width="0.127" layer="21"/>
<wire x1="-2.275" y1="-3.575" x2="-1.625" y2="-3.575" width="0.127" layer="21"/>
<wire x1="-1.625" y1="-3.575" x2="-0.975" y2="-3.575" width="0.127" layer="21"/>
<wire x1="-1.625" y1="-3.575" x2="-1.625" y2="-4.225" width="0.127" layer="21"/>
<polygon width="0.127" layer="21">
<vertex x="-2.275" y="-3.575"/>
<vertex x="-0.975" y="-3.575"/>
<vertex x="-0.975" y="-4.225"/>
<vertex x="-2.275" y="-4.225"/>
</polygon>
<wire x1="-1.625" y1="-2.275" x2="-1.625" y2="-3.575" width="0.127" layer="21"/>
<rectangle x1="-2.286" y1="-2.286" x2="-1.016" y2="-1.016" layer="21"/>
</package>
<package name="3.5MM-JACK-SWITCH-13MM-NOHOLES">
<wire x1="-4.2" y1="-1.25" x2="-3.2" y2="-1.25" width="0" layer="46"/>
<wire x1="-3.2" y1="-1.25" x2="-3.2" y2="1.25" width="0" layer="46"/>
<wire x1="-3.2" y1="1.25" x2="-4.2" y2="1.25" width="0" layer="46"/>
<wire x1="-4.2" y1="1.25" x2="-4.2" y2="-1.25" width="0" layer="46"/>
<wire x1="3.2" y1="-1.25" x2="4.2" y2="-1.25" width="0" layer="46"/>
<wire x1="4.2" y1="-1.25" x2="4.2" y2="1.25" width="0" layer="46"/>
<wire x1="4.2" y1="1.25" x2="3.2" y2="1.25" width="0" layer="46"/>
<wire x1="3.2" y1="1.25" x2="3.2" y2="-1.25" width="0" layer="46"/>
<wire x1="1.25" y1="4" x2="1.25" y2="5" width="0" layer="46"/>
<wire x1="1.25" y1="5" x2="-1.25" y2="5" width="0" layer="46"/>
<wire x1="-1.25" y1="5" x2="-1.25" y2="4" width="0" layer="46"/>
<wire x1="-1.25" y1="4" x2="1.25" y2="4" width="0" layer="46"/>
<wire x1="1.25" y1="-4" x2="1.25" y2="-3" width="0" layer="46"/>
<wire x1="1.25" y1="-3" x2="-1.25" y2="-3" width="0" layer="46"/>
<wire x1="-1.25" y1="-3" x2="-1.25" y2="-4" width="0" layer="46"/>
<wire x1="-1.25" y1="-4" x2="1.25" y2="-4" width="0" layer="46"/>
<circle x="0" y="0" radius="4" width="0.0254" layer="255"/>
<smd name="RING_T@3" x="-3.7" y="0" dx="3.85" dy="1.95" layer="1" roundness="100" rot="R90" cream="no"/>
<smd name="SWITCH_T@3" x="3.7" y="0" dx="3.85" dy="1.95" layer="1" roundness="100" rot="R90" cream="no"/>
<smd name="SECOND_T@3" x="0" y="-3.5" dx="3.85" dy="1.95" layer="1" roundness="100" rot="R180" cream="no"/>
<smd name="TIP_T@3" x="0" y="4.5" dx="3.85" dy="1.95" layer="1" roundness="100" rot="R180" cream="no"/>
<smd name="TIP_B@1" x="0" y="4.5" dx="3.85" dy="1.95" layer="16" roundness="100" cream="no"/>
<smd name="RING_B@1" x="-3.7" y="0" dx="3.85" dy="1.95" layer="16" roundness="100" rot="R90" cream="no"/>
<smd name="SWITCH_B@1" x="3.7" y="0" dx="3.85" dy="1.95" layer="16" roundness="100" rot="R90" cream="no"/>
<smd name="SECOND_B@1" x="0" y="-3.5" dx="3.85" dy="1.95" layer="16" roundness="100" cream="no"/>
<text x="0" y="0" size="1.27" layer="22" rot="SMR45" align="center">>DESC</text>
<wire x1="-4.25" y1="1.75" x2="-4.25" y2="5" width="0.127" layer="21"/>
<wire x1="-4.25" y1="5" x2="-1.75" y2="5" width="0.127" layer="21"/>
<wire x1="1.75" y1="5" x2="4.25" y2="5" width="0.127" layer="21"/>
<wire x1="4.25" y1="5" x2="4.25" y2="1.75" width="0.127" layer="21"/>
<wire x1="4.25" y1="-1.75" x2="4.25" y2="-4" width="0.127" layer="21"/>
<wire x1="4.25" y1="-4" x2="1.75" y2="-4" width="0.127" layer="21"/>
<wire x1="-1.75" y1="-4" x2="-4.25" y2="-4" width="0.127" layer="21"/>
<wire x1="-4.25" y1="-4" x2="-4.25" y2="-1.75" width="0.127" layer="21"/>
<text x="-5" y="6" size="1.27" layer="254" align="center-left">>DESC</text>
<circle x="0" y="0" radius="1.8" width="0.127" layer="254"/>
<circle x="0" y="0" radius="3.9" width="0.1" layer="254"/>
<wire x1="-5" y1="5" x2="-5" y2="0" width="0.127" layer="254"/>
<wire x1="-5" y1="0" x2="0" y2="-5" width="0.127" layer="254" curve="90"/>
<wire x1="0" y1="-5" x2="5" y2="0" width="0.127" layer="254" curve="90"/>
<wire x1="5" y1="0" x2="0" y2="5" width="0.127" layer="254" curve="90"/>
<wire x1="0" y1="5" x2="-5" y2="5" width="0.127" layer="254"/>
</package>
<package name="POWER_16_SHROUDED">
<pad name="1" x="-8.89" y="-1.27" drill="1.016" diameter="1.8796" shape="square"/>
<pad name="2" x="-8.89" y="1.27" drill="1.016" diameter="1.8796"/>
<pad name="3" x="-6.35" y="-1.27" drill="1.016" diameter="1.8796"/>
<pad name="4" x="-6.35" y="1.27" drill="1.016" diameter="1.8796"/>
<pad name="5" x="-3.81" y="-1.27" drill="1.016" diameter="1.8796"/>
<pad name="6" x="-3.81" y="1.27" drill="1.016" diameter="1.8796"/>
<pad name="7" x="-1.27" y="-1.27" drill="1.016" diameter="1.8796"/>
<pad name="8" x="-1.27" y="1.27" drill="1.016" diameter="1.8796"/>
<pad name="9" x="1.27" y="-1.27" drill="1.016" diameter="1.8796"/>
<pad name="10" x="1.27" y="1.27" drill="1.016" diameter="1.8796"/>
<pad name="11" x="3.81" y="-1.27" drill="1.016" diameter="1.8796"/>
<pad name="12" x="3.81" y="1.27" drill="1.016" diameter="1.8796"/>
<pad name="13" x="6.35" y="-1.27" drill="1.016" diameter="1.8796"/>
<pad name="14" x="6.35" y="1.27" drill="1.016" diameter="1.8796"/>
<pad name="15" x="8.89" y="-1.27" drill="1.016" diameter="1.8796"/>
<pad name="16" x="8.89" y="1.27" drill="1.016" diameter="1.8796"/>
<text x="-8.89" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">-12</text>
<text x="-6.35" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">GND</text>
<text x="-3.81" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">GND</text>
<text x="-1.27" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">GND</text>
<text x="1.27" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">+12</text>
<text x="3.81" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">+5V</text>
<text x="6.35" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">CV</text>
<text x="8.89" y="-9.525" size="1.27" layer="21" rot="R90" align="center-left">GATE</text>
<wire x1="-13.96" y1="4.4" x2="13.96" y2="4.4" width="0.127" layer="21"/>
<wire x1="13.96" y1="4.4" x2="13.96" y2="-4.4" width="0.127" layer="21"/>
<wire x1="10.16" y1="-10.16" x2="7.62" y2="-10.16" width="0.127" layer="21"/>
<wire x1="7.62" y1="-10.16" x2="5.08" y2="-10.16" width="0.127" layer="21"/>
<wire x1="5.08" y1="-10.16" x2="2.54" y2="-10.16" width="0.127" layer="21"/>
<wire x1="2.54" y1="-10.16" x2="0" y2="-10.16" width="0.127" layer="21"/>
<wire x1="0" y1="-10.16" x2="-2.54" y2="-10.16" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-10.16" x2="-5.08" y2="-10.16" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-10.16" x2="-7.62" y2="-10.16" width="0.127" layer="21"/>
<wire x1="-7.62" y1="-10.16" x2="-13.97" y2="-10.16" width="0.127" layer="21"/>
<rectangle x1="-13.97" y1="-10.16" x2="-10.16" y2="4.445" layer="21"/>
<wire x1="-2.54" y1="-4.445" x2="-2.54" y2="-3.81" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-3.81" x2="-10.795" y2="-3.81" width="0.127" layer="21"/>
<wire x1="-10.16" y1="3.81" x2="13.335" y2="3.81" width="0.127" layer="21"/>
<wire x1="13.335" y1="3.81" x2="13.335" y2="-3.81" width="0.127" layer="21"/>
<wire x1="13.335" y1="-3.81" x2="2.54" y2="-3.81" width="0.127" layer="21"/>
<wire x1="2.54" y1="-3.81" x2="2.54" y2="-4.445" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-4.445" x2="-5.08" y2="-4.445" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-4.445" x2="-7.62" y2="-4.445" width="0.127" layer="21"/>
<wire x1="-7.62" y1="-4.445" x2="-10.16" y2="-4.445" width="0.127" layer="21"/>
<wire x1="2.54" y1="-4.445" x2="5.08" y2="-4.445" width="0.127" layer="21"/>
<wire x1="5.08" y1="-4.445" x2="7.62" y2="-4.445" width="0.127" layer="21"/>
<wire x1="7.62" y1="-4.445" x2="10.16" y2="-4.445" width="0.127" layer="21"/>
<wire x1="10.16" y1="-10.16" x2="10.16" y2="-9.525" width="0.127" layer="21"/>
<wire x1="10.16" y1="-8.89" x2="10.16" y2="-8.255" width="0.127" layer="21"/>
<wire x1="10.16" y1="-8.255" x2="10.16" y2="-7.62" width="0.127" layer="21"/>
<wire x1="10.16" y1="-7.62" x2="10.16" y2="-6.985" width="0.127" layer="21"/>
<wire x1="10.16" y1="-6.985" x2="10.16" y2="-6.35" width="0.127" layer="21"/>
<wire x1="10.16" y1="-6.35" x2="10.16" y2="-5.715" width="0.127" layer="21"/>
<wire x1="10.16" y1="-5.715" x2="10.16" y2="-5.08" width="0.127" layer="21"/>
<wire x1="10.16" y1="-5.08" x2="10.16" y2="-4.445" width="0.127" layer="21"/>
<wire x1="10.16" y1="-4.445" x2="10.795" y2="-4.445" width="0.127" layer="21"/>
<wire x1="10.795" y1="-4.445" x2="11.43" y2="-4.445" width="0.127" layer="21"/>
<wire x1="11.43" y1="-4.445" x2="12.065" y2="-4.445" width="0.127" layer="21"/>
<wire x1="12.065" y1="-4.445" x2="12.7" y2="-4.445" width="0.127" layer="21"/>
<wire x1="12.7" y1="-4.445" x2="13.335" y2="-4.445" width="0.127" layer="21"/>
<wire x1="13.335" y1="-4.445" x2="13.97" y2="-4.445" width="0.127" layer="21"/>
<wire x1="-7.62" y1="-10.16" x2="-7.62" y2="-4.445" width="0.127" layer="21"/>
<wire x1="-5.08" y1="-4.445" x2="-5.08" y2="-10.16" width="0.127" layer="21"/>
<wire x1="-2.54" y1="-4.445" x2="-2.54" y2="-10.16" width="0.127" layer="21"/>
<wire x1="2.54" y1="-10.16" x2="2.54" y2="-4.445" width="0.127" layer="21"/>
<wire x1="0" y1="-10.16" x2="0" y2="-4.445" width="0.127" layer="21"/>
<wire x1="5.08" y1="-10.16" x2="5.08" y2="-4.445" width="0.127" layer="21"/>
<wire x1="7.62" y1="-10.16" x2="7.62" y2="-4.445" width="0.127" layer="21"/>
<wire x1="10.16" y1="-10.16" x2="10.795" y2="-10.16" width="0.127" layer="21"/>
<wire x1="10.795" y1="-10.16" x2="11.43" y2="-10.16" width="0.127" layer="21"/>
<wire x1="11.43" y1="-10.16" x2="12.065" y2="-10.16" width="0.127" layer="21"/>
<wire x1="12.065" y1="-10.16" x2="12.7" y2="-10.16" width="0.127" layer="21"/>
<wire x1="12.7" y1="-10.16" x2="13.335" y2="-10.16" width="0.127" layer="21"/>
<wire x1="13.335" y1="-10.16" x2="13.97" y2="-10.16" width="0.127" layer="21"/>
<wire x1="13.97" y1="-10.16" x2="13.97" y2="-9.525" width="0.127" layer="21"/>
<wire x1="13.97" y1="-9.525" x2="13.97" y2="-8.89" width="0.127" layer="21"/>
<wire x1="13.97" y1="-8.89" x2="13.97" y2="-8.255" width="0.127" layer="21"/>
<wire x1="13.97" y1="-8.255" x2="13.97" y2="-7.62" width="0.127" layer="21"/>
<wire x1="13.97" y1="-7.62" x2="13.97" y2="-6.985" width="0.127" layer="21"/>
<wire x1="13.97" y1="-6.985" x2="13.97" y2="-6.35" width="0.127" layer="21"/>
<wire x1="13.97" y1="-6.35" x2="13.97" y2="-5.715" width="0.127" layer="21"/>
<wire x1="13.97" y1="-5.715" x2="13.97" y2="-5.08" width="0.127" layer="21"/>
<wire x1="13.97" y1="-5.08" x2="13.97" y2="-4.445" width="0.127" layer="21"/>
<wire x1="10.16" y1="-5.08" x2="10.795" y2="-4.445" width="0.127" layer="21"/>
<wire x1="11.43" y1="-4.445" x2="10.16" y2="-5.715" width="0.127" layer="21"/>
<wire x1="12.065" y1="-4.445" x2="10.16" y2="-6.35" width="0.127" layer="21"/>
<wire x1="10.16" y1="-6.985" x2="12.7" y2="-4.445" width="0.127" layer="21"/>
<wire x1="13.335" y1="-4.445" x2="10.16" y2="-7.62" width="0.127" layer="21"/>
<wire x1="10.16" y1="-8.255" x2="13.97" y2="-4.445" width="0.127" layer="21"/>
<wire x1="13.97" y1="-5.08" x2="10.16" y2="-8.89" width="0.127" layer="21"/>
<wire x1="10.16" y1="-8.89" x2="10.16" y2="-9.525" width="0.127" layer="21"/>
<wire x1="10.16" y1="-9.525" x2="13.97" y2="-5.715" width="0.127" layer="21"/>
<wire x1="13.97" y1="-6.35" x2="10.16" y2="-10.16" width="0.127" layer="21"/>
<wire x1="10.795" y1="-10.16" x2="13.97" y2="-6.985" width="0.127" layer="21"/>
<wire x1="13.97" y1="-7.62" x2="11.43" y2="-10.16" width="0.127" layer="21"/>
<wire x1="12.065" y1="-10.16" x2="13.97" y2="-8.255" width="0.127" layer="21"/>
<wire x1="13.97" y1="-8.89" x2="12.7" y2="-10.16" width="0.127" layer="21"/>
<wire x1="13.335" y1="-10.16" x2="13.97" y2="-9.525" width="0.127" layer="21"/>
<wire x1="-13.97" y1="4.445" x2="-13.97" y2="-10.16" width="0.127" layer="21"/>
</package>
<package name="EURORACK36HP_5STOMP">
<wire x1="178.5" y1="108.08" x2="2.844003125" y2="108.08" width="0.127" layer="20"/>
<wire x1="2.844003125" y1="108.08" x2="0.34400625" y2="105.57609375" width="0.127" layer="20" curve="90.089525"/>
<wire x1="0.34400625" y1="105.57609375" x2="0.34400625" y2="91.595" width="0.127" layer="20"/>
<wire x1="0.34400625" y1="91.595" x2="2.84400625" y2="89.095" width="0.127" layer="20" curve="90"/>
<wire x1="2.84400625" y1="89.095" x2="21.5" y2="89.095" width="0.127" layer="20"/>
<wire x1="21.5" y1="89.095" x2="24" y2="86.595" width="0.127" layer="20" curve="-90"/>
<wire x1="24" y1="86.595" x2="24" y2="65.345" width="0.127" layer="20"/>
<wire x1="24" y1="65.345" x2="21.5" y2="62.845" width="0.127" layer="20" curve="-90"/>
<wire x1="21.5" y1="62.845" x2="2.84400625" y2="62.845" width="0.127" layer="20"/>
<wire x1="2.84400625" y1="62.845" x2="0.34400625" y2="60.345" width="0.127" layer="20" curve="90"/>
<wire x1="0.34400625" y1="60.345" x2="0.34400625" y2="5.49609375" width="0.127" layer="20"/>
<wire x1="0.34400625" y1="5.49609375" x2="2.996003125" y2="3" width="0.127" layer="20" curve="89.908327"/>
<wire x1="2.996003125" y1="3" x2="7.64838125" y2="3" width="0.127" layer="20"/>
<wire x1="175.5" y1="3" x2="178.5" y2="3" width="0.127" layer="20"/>
<wire x1="178.5" y1="3" x2="181" y2="5.5" width="0.127" layer="20" curve="90"/>
<wire x1="181" y1="5.5" x2="181" y2="105.58" width="0.127" layer="20"/>
<wire x1="181" y1="105.58" x2="178.5" y2="108.08" width="0.127" layer="20" curve="90"/>
<wire x1="0" y1="-11" x2="182.54" y2="-11" width="0" layer="255"/>
<wire x1="182.54" y1="-11" x2="182.54" y2="117.5" width="0" layer="255"/>
<wire x1="182.54" y1="117.5" x2="0" y2="117.5" width="0" layer="255"/>
<wire x1="0" y1="117.5" x2="0" y2="-11" width="0" layer="255"/>
<text x="1.5" y="113" size="1.27" layer="51">36HP eurorack pcb template</text>
<wire x1="91.27" y1="112.08" x2="91.27" y2="-5.92" width="0.127" layer="51"/>
<circle x="7.5" y="-8" radius="1.5" width="0.0254" layer="255"/>
<circle x="7.5" y="114.5" radius="1.5" width="0.0254" layer="255"/>
<wire x1="0" y1="0" x2="3.84" y2="7" width="0.127" layer="51"/>
<circle x="175.14" y="-8" radius="1.5" width="0.0254" layer="255"/>
<circle x="175.14" y="114.5" radius="1.5" width="0.0254" layer="255"/>
<circle x="20.32" y="25.4" radius="1.525" width="0.127" layer="48"/>
<circle x="55.88" y="25.4" radius="1.525" width="0.127" layer="48"/>
<circle x="91.44" y="25.4" radius="1.525" width="0.127" layer="48"/>
<circle x="127" y="25.4" radius="1.525" width="0.127" layer="48"/>
<circle x="162.56" y="25.4" radius="1.525" width="0.127" layer="48"/>
<circle x="20.32" y="10.16" radius="6.15" width="0.127" layer="48"/>
<circle x="55.88" y="10.16" radius="6.15" width="0.127" layer="48"/>
<circle x="91.44" y="10.16" radius="6.15" width="0.127" layer="48"/>
<circle x="127" y="10.16" radius="6.15" width="0.127" layer="48"/>
<circle x="162.56" y="10.16" radius="6.15" width="0.127" layer="48"/>
<wire x1="7.64838125" y1="3" x2="9.5" y2="4.85161875" width="0.127" layer="20" curve="90"/>
<wire x1="9.5" y1="4.85161875" x2="9.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="9.5" y1="20.5" x2="15" y2="20.5" width="0.127" layer="20"/>
<wire x1="15" y1="20.5" x2="17.5" y2="23" width="0.127" layer="20" curve="90"/>
<wire x1="17.5" y1="23" x2="17.5" y2="28" width="0.127" layer="20"/>
<wire x1="17.5" y1="28" x2="23" y2="28" width="0.127" layer="20"/>
<wire x1="23" y1="28" x2="23" y2="23" width="0.127" layer="20"/>
<wire x1="23" y1="23" x2="25.5" y2="20.5" width="0.127" layer="20" curve="90"/>
<wire x1="25.5" y1="20.5" x2="30.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="30.5" y1="20.5" x2="30.5" y2="5.5" width="0.127" layer="20"/>
<wire x1="30.5" y1="5.5" x2="33" y2="3" width="0.127" layer="20" curve="90"/>
<wire x1="33" y1="3" x2="43" y2="3" width="0.127" layer="20"/>
<wire x1="43" y1="3" x2="45.5" y2="5.5" width="0.127" layer="20" curve="90"/>
<wire x1="45.5" y1="5.5" x2="45.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="45.5" y1="20.5" x2="50.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="50.5" y1="20.5" x2="53" y2="23" width="0.127" layer="20" curve="90"/>
<wire x1="53" y1="23" x2="53" y2="28" width="0.127" layer="20"/>
<wire x1="53" y1="28" x2="58.5" y2="28" width="0.127" layer="20"/>
<wire x1="58.5" y1="28" x2="58.5" y2="23" width="0.127" layer="20"/>
<wire x1="58.5" y1="23" x2="61" y2="20.5" width="0.127" layer="20" curve="90"/>
<wire x1="61" y1="20.5" x2="66.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="66.5" y1="20.5" x2="66.5" y2="5.5" width="0.127" layer="20"/>
<wire x1="66.5" y1="5.5" x2="69" y2="3" width="0.127" layer="20" curve="90"/>
<wire x1="69" y1="3" x2="78.5" y2="3" width="0.127" layer="20"/>
<wire x1="78.5" y1="3" x2="81" y2="5.5" width="0.127" layer="20" curve="90"/>
<wire x1="81" y1="5.5" x2="81" y2="20.5" width="0.127" layer="20"/>
<wire x1="81" y1="20.5" x2="86" y2="20.5" width="0.127" layer="20"/>
<wire x1="86" y1="20.5" x2="88.5" y2="23" width="0.127" layer="20" curve="90"/>
<wire x1="88.5" y1="23" x2="88.5" y2="28" width="0.127" layer="20"/>
<wire x1="88.5" y1="28" x2="94.5" y2="28" width="0.127" layer="20"/>
<wire x1="94.5" y1="28" x2="94.5" y2="23" width="0.127" layer="20"/>
<wire x1="94.5" y1="23" x2="97" y2="20.5" width="0.127" layer="20" curve="90"/>
<wire x1="97" y1="20.5" x2="102" y2="20.5" width="0.127" layer="20"/>
<wire x1="102" y1="20.5" x2="102" y2="5.5" width="0.127" layer="20"/>
<wire x1="102" y1="5.5" x2="104.5" y2="3" width="0.127" layer="20" curve="90"/>
<wire x1="104.5" y1="3" x2="114" y2="3" width="0.127" layer="20"/>
<wire x1="114" y1="3" x2="116.5" y2="5.5" width="0.127" layer="20" curve="90"/>
<wire x1="116.5" y1="5.5" x2="116.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="116.5" y1="20.5" x2="121.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="121.5" y1="20.5" x2="124" y2="23" width="0.127" layer="20" curve="90"/>
<wire x1="124" y1="23" x2="124" y2="28.5" width="0.127" layer="20"/>
<wire x1="124" y1="28.5" x2="130" y2="28.5" width="0.127" layer="20"/>
<wire x1="130" y1="28.5" x2="130" y2="23" width="0.127" layer="20"/>
<wire x1="130" y1="23" x2="132.5" y2="20.5" width="0.127" layer="20" curve="90"/>
<wire x1="132.5" y1="20.5" x2="137.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="137.5" y1="20.5" x2="137.5" y2="5.5" width="0.127" layer="20"/>
<wire x1="137.5" y1="5.5" x2="140" y2="3" width="0.127" layer="20" curve="90"/>
<wire x1="140" y1="3" x2="149.5" y2="3" width="0.127" layer="20"/>
<wire x1="149.5" y1="3" x2="152" y2="5.5" width="0.127" layer="20" curve="90"/>
<wire x1="152" y1="5.5" x2="152" y2="20.5" width="0.127" layer="20"/>
<wire x1="152" y1="20.5" x2="157.5" y2="20.5" width="0.127" layer="20"/>
<wire x1="157.5" y1="20.5" x2="160" y2="23" width="0.127" layer="20" curve="90"/>
<wire x1="160" y1="23" x2="160" y2="28" width="0.127" layer="20"/>
<wire x1="160" y1="28" x2="165.5" y2="28" width="0.127" layer="20"/>
<wire x1="165.5" y1="28" x2="165.5" y2="23" width="0.127" layer="20"/>
<wire x1="165.5" y1="23" x2="168" y2="20.5" width="0.127" layer="20" curve="90"/>
<wire x1="168" y1="20.5" x2="173" y2="20.5" width="0.127" layer="20"/>
<wire x1="173" y1="20.5" x2="173" y2="5.5" width="0.127" layer="20"/>
<wire x1="173" y1="5.5" x2="175.5" y2="3" width="0.127" layer="20" curve="90"/>
</package>
<package name="BYPASSBOARD">
<pad name="P$1" x="31.75" y="5.08" drill="0.8" shape="square"/>
<pad name="P$2" x="31.75" y="10.16" drill="0.8"/>
<pad name="P$3" x="31.75" y="7.62" drill="0.8"/>
<pad name="P$4" x="31.75" y="12.7" drill="0.8"/>
<pad name="P$5" x="34.29" y="15.24" drill="0.8"/>
<pad name="P$6" x="34.29" y="10.16" drill="0.8"/>
<pad name="P$7" x="34.29" y="12.7" drill="0.8"/>
<pad name="P$8" x="34.29" y="7.62" drill="0.8"/>
<pad name="P$9" x="104.14" y="5.08" drill="0.8"/>
<pad name="P$10" x="104.14" y="10.16" drill="0.8"/>
<pad name="P$11" x="104.14" y="7.62" drill="0.8"/>
<pad name="P$12" x="104.14" y="12.7" drill="0.8"/>
<pad name="P$13" x="138.43" y="5.08" drill="0.8"/>
<pad name="P$14" x="138.43" y="10.16" drill="0.8"/>
<pad name="P$15" x="138.43" y="7.62" drill="0.8"/>
<pad name="P$16" x="138.43" y="12.7" drill="0.8"/>
<pad name="P$17" x="140.97" y="15.24" drill="0.8"/>
<pad name="P$18" x="140.97" y="10.16" drill="0.8"/>
<pad name="P$19" x="140.97" y="12.7" drill="0.8"/>
<pad name="P$20" x="140.97" y="7.62" drill="0.8"/>
<pad name="GND" x="34.29" y="5.08" drill="0.8" shape="long"/>
<pad name="GND2" x="138.43" y="15.24" drill="0.8" shape="long"/>
<pad name="GND3" x="140.97" y="5.08" drill="0.8" shape="long"/>
<pad name="12V" x="31.75" y="15.24" drill="0.8" shape="long"/>
<wire x1="5.08" y1="0" x2="25.4" y2="0" width="0.127" layer="48"/>
<wire x1="40.64" y1="0" x2="60.96" y2="0" width="0.127" layer="48"/>
<wire x1="76.2" y1="0" x2="96.52" y2="0" width="0.127" layer="48"/>
<wire x1="111.76" y1="0" x2="132.08" y2="0" width="0.127" layer="48"/>
<wire x1="147.32" y1="0" x2="167.64" y2="0" width="0.127" layer="48"/>
<wire x1="167.64" y1="0" x2="167.64" y2="20.32" width="0.127" layer="48"/>
<wire x1="5.08" y1="20.32" x2="5.08" y2="0" width="0.127" layer="48"/>
<wire x1="5.08" y1="20.32" x2="10.16" y2="20.32" width="0.127" layer="48"/>
<wire x1="10.16" y1="20.32" x2="12.7" y2="22.86" width="0.127" layer="48" curve="90"/>
<wire x1="12.7" y1="22.86" x2="12.7" y2="25.4" width="0.127" layer="48"/>
<wire x1="12.7" y1="25.4" x2="15.24" y2="27.94" width="0.127" layer="48" curve="-90"/>
<wire x1="15.24" y1="27.94" x2="17.78" y2="25.4" width="0.127" layer="48" curve="-90"/>
<wire x1="17.78" y1="25.4" x2="17.78" y2="22.86" width="0.127" layer="48"/>
<wire x1="40.64" y1="20.32" x2="45.72" y2="20.32" width="0.127" layer="48"/>
<wire x1="45.72" y1="20.32" x2="48.26" y2="22.86" width="0.127" layer="48" curve="90"/>
<wire x1="48.26" y1="22.86" x2="48.26" y2="25.4" width="0.127" layer="48"/>
<wire x1="48.26" y1="25.4" x2="50.8" y2="27.94" width="0.127" layer="48" curve="-90"/>
<wire x1="50.8" y1="27.94" x2="53.34" y2="25.4" width="0.127" layer="48" curve="-90"/>
<wire x1="53.34" y1="25.4" x2="53.34" y2="22.86" width="0.127" layer="48"/>
<wire x1="53.34" y1="22.86" x2="55.88" y2="20.32" width="0.127" layer="48" curve="90"/>
<wire x1="55.88" y1="20.32" x2="60.96" y2="20.32" width="0.127" layer="48"/>
<wire x1="83.82" y1="22.86" x2="83.82" y2="25.4" width="0.127" layer="48"/>
<wire x1="83.82" y1="25.4" x2="86.36" y2="27.94" width="0.127" layer="48" curve="-90"/>
<wire x1="86.36" y1="27.94" x2="88.9" y2="25.4" width="0.127" layer="48" curve="-90"/>
<wire x1="88.9" y1="25.4" x2="88.9" y2="22.86" width="0.127" layer="48"/>
<wire x1="88.9" y1="22.86" x2="91.44" y2="20.32" width="0.127" layer="48" curve="90"/>
<wire x1="91.44" y1="20.32" x2="96.52" y2="20.32" width="0.127" layer="48"/>
<wire x1="76.2" y1="20.32" x2="81.28" y2="20.32" width="0.127" layer="48"/>
<wire x1="81.28" y1="20.32" x2="83.82" y2="22.86" width="0.127" layer="48" curve="90"/>
<wire x1="157.48" y1="27.94" x2="160.02" y2="25.4" width="0.127" layer="48" curve="-90"/>
<wire x1="160.02" y1="25.4" x2="160.02" y2="22.86" width="0.127" layer="48"/>
<wire x1="157.48" y1="27.94" x2="154.94" y2="25.4" width="0.127" layer="48" curve="90"/>
<wire x1="154.94" y1="25.4" x2="154.94" y2="22.86" width="0.127" layer="48"/>
<wire x1="160.02" y1="22.86" x2="162.56" y2="20.32" width="0.127" layer="48" curve="90"/>
<wire x1="162.56" y1="20.32" x2="167.64" y2="20.32" width="0.127" layer="48"/>
<wire x1="121.92" y1="27.94" x2="124.46" y2="25.4" width="0.127" layer="48" curve="-90"/>
<wire x1="124.46" y1="25.4" x2="124.46" y2="22.86" width="0.127" layer="48"/>
<wire x1="124.46" y1="22.86" x2="127" y2="20.32" width="0.127" layer="48" curve="90"/>
<wire x1="127" y1="20.32" x2="132.08" y2="20.32" width="0.127" layer="48"/>
<wire x1="121.92" y1="27.94" x2="119.38" y2="25.4" width="0.127" layer="48" curve="90"/>
<wire x1="119.38" y1="25.4" x2="119.38" y2="22.86" width="0.127" layer="48"/>
<wire x1="119.38" y1="22.86" x2="116.84" y2="20.32" width="0.127" layer="48" curve="-90"/>
<wire x1="116.84" y1="20.32" x2="111.76" y2="20.32" width="0.127" layer="48"/>
<wire x1="17.78" y1="22.86" x2="20.32" y2="20.32" width="0.127" layer="48" curve="90"/>
<wire x1="20.32" y1="20.32" x2="25.4" y2="20.32" width="0.127" layer="48"/>
<wire x1="154.94" y1="22.86" x2="152.4" y2="20.32" width="0.127" layer="48" curve="-90"/>
<wire x1="152.4" y1="20.32" x2="147.32" y2="20.32" width="0.127" layer="48"/>
<wire x1="25.4" y1="20.32" x2="25.4" y2="0" width="0.127" layer="48"/>
<wire x1="60.96" y1="20.32" x2="60.96" y2="0" width="0.127" layer="48"/>
<wire x1="40.64" y1="20.32" x2="40.64" y2="0" width="0.127" layer="48"/>
<wire x1="76.2" y1="20.32" x2="76.2" y2="0" width="0.127" layer="48"/>
<wire x1="96.52" y1="20.32" x2="96.52" y2="0" width="0.127" layer="48"/>
<wire x1="111.76" y1="20.32" x2="111.76" y2="0" width="0.127" layer="48"/>
<wire x1="132.08" y1="20.32" x2="132.08" y2="0" width="0.127" layer="48"/>
<wire x1="147.32" y1="20.32" x2="147.32" y2="0" width="0.127" layer="48"/>
<circle x="15.24" y="25.4" radius="1.525" width="0.127" layer="255"/>
<circle x="50.8" y="25.4" radius="1.525" width="0.127" layer="255"/>
<circle x="86.36" y="25.4" radius="1.525" width="0.127" layer="255"/>
<circle x="121.92" y="25.4" radius="1.525" width="0.127" layer="255"/>
<circle x="157.48" y="25.4" radius="1.525" width="0.127" layer="255"/>
<circle x="15.24" y="10.16" radius="6.15" width="0.127" layer="255"/>
<circle x="50.8" y="10.16" radius="6.15" width="0.127" layer="255"/>
<circle x="86.36" y="10.16" radius="6.15" width="0.127" layer="255"/>
<circle x="121.92" y="10.16" radius="6.15" width="0.127" layer="255"/>
<circle x="157.48" y="10.16" radius="6.15" width="0.127" layer="255"/>
</package>
<package name="HEADPHONEHOLE_GAP">
<wire x1="-4.5" y1="8" x2="4.5" y2="8" width="0.127" layer="51"/>
<wire x1="4.5" y1="8" x2="9" y2="0" width="0.127" layer="51"/>
<wire x1="9" y1="0" x2="4.5" y2="-8" width="0.127" layer="51"/>
<wire x1="4.5" y1="-8" x2="-4.5" y2="-8" width="0.127" layer="51"/>
<wire x1="-4.5" y1="-8" x2="-9" y2="0" width="0.127" layer="51"/>
<wire x1="-9" y1="0" x2="-4.5" y2="8" width="0.127" layer="51"/>
<wire x1="-12.5" y1="12.5" x2="12.5" y2="12.5" width="0.127" layer="51"/>
<wire x1="12.5" y1="12.5" x2="12.5" y2="-12.5" width="0.127" layer="51"/>
<wire x1="12.5" y1="-12.5" x2="-12.5" y2="-12.5" width="0.127" layer="51"/>
<wire x1="-12.5" y1="-12.5" x2="-12.5" y2="12.5" width="0.127" layer="51"/>
<circle x="0" y="0" radius="5.6796125" width="0.127" layer="255"/>
</package>
</packages>
</library>
<library name="FenixBase">
<packages>
<package name="SOT-323">
<smd name="ANODE" x="-0.65" y="-0.95" dx="0.9" dy="0.7" layer="1" rot="R90"/>
<smd name="CATHODE" x="0" y="0.95" dx="0.9" dy="0.7" layer="1" rot="R90"/>
<smd name="NC" x="0.65" y="-0.95" dx="0.9" dy="0.7" layer="1" rot="R90"/>
<wire x1="-1.15" y1="-0.4" x2="-0.7" y2="-0.4" width="0.127" layer="21"/>
<wire x1="-0.7" y1="-0.4" x2="1.15" y2="-0.4" width="0.127" layer="21"/>
<wire x1="-1.15" y1="-0.4" x2="-1.15" y2="0.4" width="0.127" layer="21"/>
<wire x1="-1.15" y1="0.4" x2="1.15" y2="0.4" width="0.127" layer="21"/>
<wire x1="1.15" y1="0.4" x2="1.15" y2="-0.4" width="0.127" layer="21"/>
<wire x1="0" y1="0.35" x2="0" y2="0" width="0.127" layer="21"/>
<wire x1="0" y1="0" x2="-0.2" y2="0" width="0.127" layer="21"/>
<wire x1="-0.2" y1="0.2" x2="-0.2" y2="0" width="0.127" layer="21"/>
<wire x1="-0.2" y1="0" x2="-0.2" y2="-0.2" width="0.127" layer="21"/>
<wire x1="-0.25" y1="0" x2="-0.5" y2="0.2" width="0.127" layer="21"/>
<wire x1="-0.5" y1="0.2" x2="-0.5" y2="0" width="0.127" layer="21"/>
<wire x1="-0.5" y1="0" x2="-0.5" y2="-0.2" width="0.127" layer="21"/>
<wire x1="-0.5" y1="-0.2" x2="-0.2" y2="0" width="0.127" layer="21"/>
<wire x1="-0.4" y1="0.1" x2="-0.4" y2="-0.1" width="0.127" layer="21"/>
<wire x1="-0.5" y1="0" x2="-0.7" y2="0" width="0.127" layer="21"/>
<wire x1="-0.7" y1="0" x2="-0.7" y2="-0.4" width="0.127" layer="21"/>
<text x="0" y="0" size="0.508" layer="25" align="center">>NAME</text>
</package>
<package name="POWERTESTPAD">
<text x="0" y="-1.75" size="0.5" layer="21" align="top-center">>DESC</text>
<pad name="P$1" x="0" y="0" drill="1" diameter="2"/>
<smd name="P$2" x="0" y="-0.75" dx="2" dy="1.5" layer="1" rot="R180"/>
<smd name="P$3" x="0" y="-0.75" dx="2" dy="1.5" layer="16" rot="R180"/>
<text x="0" y="-1.75" size="0.5" layer="22" rot="MR0" align="top-center">>DESC</text>
<wire x1="1.25" y1="-2.25" x2="1.25" y2="0" width="0.127" layer="21"/>
<wire x1="1.25" y1="0" x2="0" y2="1.25" width="0.127" layer="21" curve="90"/>
<wire x1="0" y1="1.25" x2="-1.25" y2="0" width="0.127" layer="21" curve="90"/>
<wire x1="-1.25" y1="0" x2="-1.25" y2="-2.25" width="0.127" layer="21"/>
<wire x1="-1.25" y1="-2.25" x2="-1" y2="-2.5" width="0.127" layer="21" curve="90"/>
<wire x1="-1" y1="-2.5" x2="1" y2="-2.5" width="0.127" layer="21"/>
<wire x1="1" y1="-2.5" x2="1.25" y2="-2.25" width="0.127" layer="21" curve="90"/>
<wire x1="-1.25" y1="-2.25" x2="-1.25" y2="0" width="0.127" layer="22"/>
<wire x1="-1.25" y1="0" x2="0" y2="1.25" width="0.127" layer="22" curve="-90"/>
<wire x1="0" y1="1.25" x2="1.25" y2="0" width="0.127" layer="22" curve="-90"/>
<wire x1="1.25" y1="0" x2="1.25" y2="-2.25" width="0.127" layer="22"/>
<wire x1="1.25" y1="-2.25" x2="1" y2="-2.5" width="0.127" layer="22" curve="-90"/>
<wire x1="1" y1="-2.5" x2="-1" y2="-2.5" width="0.127" layer="22"/>
<wire x1="-1" y1="-2.5" x2="-1.25" y2="-2.25" width="0.127" layer="22" curve="-90"/>
</package>
<package name="FENIXINTERNALCONNECTIONPAD">
<smd name="P$1" x="0" y="0" dx="1.27" dy="0.635" layer="16" rot="R90"/>
<text x="-0.762" y="0" size="0.762" layer="52" rot="R90" align="center-left">>NAME</text>
</package>
<package name="SOT23">
<smd name="P$1" x="-0.85" y="-1" dx="0.7" dy="0.6" layer="1" rot="R90"/>
<smd name="P$2" x="0.85" y="-1" dx="0.7" dy="0.6" layer="1" rot="R90"/>
<smd name="P$3" x="0" y="1" dx="0.7" dy="0.6" layer="1" rot="R90"/>
<wire x1="-1.2" y1="0.5" x2="-1.2" y2="-0.5" width="0.127" layer="21"/>
<wire x1="-1.2" y1="-0.5" x2="-0.8" y2="-0.5" width="0.127" layer="21"/>
<wire x1="-0.8" y1="-0.5" x2="0.8" y2="-0.5" width="0.127" layer="21"/>
<wire x1="0.8" y1="-0.5" x2="1.2" y2="-0.5" width="0.127" layer="21"/>
<wire x1="1.2" y1="-0.5" x2="1.2" y2="0.5" width="0.127" layer="21"/>
<wire x1="1.2" y1="0.5" x2="-1.2" y2="0.5" width="0.127" layer="21"/>
<wire x1="0" y1="0.4" x2="0" y2="0" width="0.127" layer="21"/>
<wire x1="0" y1="0" x2="-0.2" y2="0" width="0.127" layer="21"/>
<wire x1="-0.2" y1="0.3" x2="-0.2" y2="0" width="0.127" layer="21"/>
<wire x1="-0.2" y1="0" x2="-0.2" y2="-0.3" width="0.127" layer="21"/>
<wire x1="0" y1="0" x2="0.5" y2="0" width="0.127" layer="21"/>
<wire x1="0.5" y1="0" x2="0.8" y2="0" width="0.127" layer="21"/>
<wire x1="0.8" y1="0" x2="0.8" y2="-0.5" width="0.127" layer="21"/>
<wire x1="-0.8" y1="-0.5" x2="-0.8" y2="0" width="0.127" layer="21"/>
<wire x1="-0.8" y1="0" x2="-0.2" y2="0" width="0.127" layer="21"/>
<wire x1="-0.2" y1="0.3" x2="-0.15" y2="0.3" width="0.127" layer="21"/>
<wire x1="-0.2" y1="-0.3" x2="-0.25" y2="-0.3" width="0.127" layer="21"/>
<wire x1="-0.3" y1="0.1" x2="-0.5" y2="0.3" width="0.127" layer="21"/>
<wire x1="-0.5" y1="0.3" x2="-0.5" y2="0.1" width="0.127" layer="21"/>
<wire x1="-0.5" y1="-0.1" x2="-0.5" y2="-0.3" width="0.127" layer="21"/>
<wire x1="-0.5" y1="-0.3" x2="-0.3" y2="-0.1" width="0.127" layer="21"/>
<wire x1="-0.3" y1="-0.1" x2="-0.2" y2="0" width="0.127" layer="21"/>
<wire x1="-0.2" y1="0" x2="-0.3" y2="0.1" width="0.127" layer="21"/>
<wire x1="-0.3" y1="0.1" x2="-0.5" y2="0.1" width="0.127" layer="21"/>
<wire x1="-0.5" y1="0.1" x2="-0.5" y2="-0.1" width="0.127" layer="21"/>
<wire x1="-0.5" y1="-0.1" x2="-0.3" y2="-0.1" width="0.127" layer="21"/>
<wire x1="0.2" y1="0.3" x2="0.2" y2="0.1" width="0.127" layer="21"/>
<wire x1="0.2" y1="0.1" x2="0.2" y2="-0.1" width="0.127" layer="21"/>
<wire x1="0.2" y1="-0.1" x2="0.2" y2="-0.3" width="0.127" layer="21"/>
<wire x1="0.2" y1="-0.3" x2="0.5" y2="0" width="0.127" layer="21"/>
<wire x1="0.5" y1="0" x2="0.4" y2="0.1" width="0.127" layer="21"/>
<wire x1="0.4" y1="0.1" x2="0.2" y2="0.3" width="0.127" layer="21"/>
<wire x1="0.4" y1="0.1" x2="0.2" y2="0.1" width="0.127" layer="21"/>
<wire x1="0.3" y1="-0.1" x2="0.2" y2="-0.1" width="0.127" layer="21"/>
<wire x1="0.5" y1="0.3" x2="0.5" y2="-0.3" width="0.127" layer="21"/>
<wire x1="0.5" y1="-0.3" x2="0.45" y2="-0.3" width="0.127" layer="21"/>
<wire x1="0.5" y1="0.3" x2="0.55" y2="0.3" width="0.127" layer="21"/>
</package>
<package name="TESTPAD_DUAL_PTH">
<text x="0" y="1.016" size="0.762" layer="21" align="bottom-center">>DESC</text>
<wire x1="-2.286" y1="0.762" x2="-2.286" y2="-1.016" width="0.127" layer="21"/>
<wire x1="-2.286" y1="-1.016" x2="2.286" y2="-1.016" width="0.127" layer="21"/>
<wire x1="2.286" y1="-1.016" x2="2.286" y2="0.762" width="0.127" layer="21"/>
<pad name="P$1" x="-1.27" y="0" drill="0.8" shape="square"/>
<pad name="P$2" x="1.27" y="0" drill="0.8"/>
</package>
<package name="GROUNDLOOP">
<pad name="P$1" x="1.27" y="0" drill="0.8" shape="offset" rot="R270"/>
<pad name="P$2" x="-1.27" y="0" drill="0.8" shape="offset" rot="R270"/>
<wire x1="0.635" y1="0" x2="-0.635" y2="0" width="0.127" layer="21"/>
<wire x1="-0.635" y1="0" x2="-0.635" y2="-1.27" width="0.127" layer="21"/>
<wire x1="-0.635" y1="-1.27" x2="0.635" y2="-1.27" width="0.127" layer="21"/>
<wire x1="0.635" y1="-1.27" x2="0.635" y2="0" width="0.127" layer="21"/>
<rectangle x1="-0.635" y1="-1.27" x2="0.635" y2="0" layer="21" rot="R180"/>
<rectangle x1="-0.3175" y1="-3.81" x2="0.3175" y2="-1.27" layer="21" rot="R180"/>
<rectangle x1="-2.54" y1="-2.54" x2="2.54" y2="-2.2225" layer="21" rot="R180"/>
<rectangle x1="-1.905" y1="-3.175" x2="1.905" y2="-2.8575" layer="21" rot="R180"/>
<rectangle x1="-1.27" y1="-3.81" x2="1.27" y2="-3.4925" layer="21" rot="R180"/>
<rectangle x1="-0.3175" y1="-3.81" x2="0.3175" y2="-1.27" layer="22"/>
<rectangle x1="-2.54" y1="-2.54" x2="2.54" y2="-2.2225" layer="22"/>
<rectangle x1="-1.905" y1="-3.175" x2="1.905" y2="-2.8575" layer="22"/>
<rectangle x1="-1.27" y1="-3.81" x2="1.27" y2="-3.4925" layer="22"/>
<wire x1="-0.635" y1="0" x2="0.635" y2="0" width="0.127" layer="22"/>
<wire x1="0.635" y1="0" x2="0.635" y2="-1.27" width="0.127" layer="22"/>
<wire x1="0.635" y1="-1.27" x2="-0.635" y2="-1.27" width="0.127" layer="22"/>
<wire x1="-0.635" y1="-1.27" x2="-0.635" y2="0" width="0.127" layer="22"/>
<rectangle x1="-0.635" y1="-1.27" x2="0.635" y2="0" layer="22"/>
</package>
</packages>
</library>
<library name="linear">
<description><b>Linear Devices</b><p>
Operational amplifiers,  comparators, voltage regulators, ADCs, DACs, etc.<p>
<author>Created by librarian@cadsoft.de</author></description>
<packages>
<package name="SO08">
<description><b>Small Outline Package 8</b><br>
NS Package M08A</description>
<wire x1="2.4" y1="1.9" x2="2.4" y2="-1.4" width="0.2032" layer="51"/>
<wire x1="2.4" y1="-1.4" x2="2.4" y2="-1.9" width="0.2032" layer="51"/>
<wire x1="2.4" y1="-1.9" x2="-2.4" y2="-1.9" width="0.2032" layer="51"/>
<wire x1="-2.4" y1="-1.9" x2="-2.4" y2="-1.4" width="0.2032" layer="51"/>
<wire x1="-2.4" y1="-1.4" x2="-2.4" y2="1.9" width="0.2032" layer="51"/>
<wire x1="-2.4" y1="1.9"

repository: ThisIsNotRocketScience/Eurorack-Modules

repo_name: ThisIsNotRocketScience/Eurorack-Modules

extension: brd