text:
package com.cisco.axl.api._8;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

/**
 *
Java class for RUnitsToGateway complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="RUnitsToGateway">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence minOccurs="0">
 *         <choice minOccurs="0">
 *           <element name="domainName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *           <element name="gatewayUuid" type="{http://www.cisco.com/AXL/API/8.0}XUUID" minOccurs="0"/>
 *         </choice>
 *         <element name="units" minOccurs="0">
 *           <complexType>
 *             <complexContent>
 *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *                 <sequence minOccurs="0">
 *                   <element name="unit" maxOccurs="unbounded" minOccurs="0">
 *                     <complexType>
 *                       <complexContent>
 *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *                           <sequence minOccurs="0">
 *                             <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
 *                             <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPSlotModule" minOccurs="0"/>
 *                             <element name="subunits" minOccurs="0">
 *                               <complexType>
 *                                 <complexContent>
 *                                   <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *                                     <sequence minOccurs="0">
 *                                       <element name="subunit" maxOccurs="unbounded" minOccurs="0">
 *                                         <complexType>
 *                                           <complexContent>
 *                                             <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *                                               <sequence minOccurs="0">
 *                                                 <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
 *                                                 <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPVic" minOccurs="0"/>
 *                                                 <element name="beginPort" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
 *                                               </sequence>
 *                                             </restriction>
 *                                           </complexContent>
 *                                         </complexType>
 *                                       </element>
 *                                     </sequence>
 *                                   </restriction>
 *                                 </complexContent>
 *                               </complexType>
 *                             </element>
 *                           </sequence>
 *                         </restriction>
 *                       </complexContent>
 *                     </complexType>
 *                   </element>
 *                 </sequence>
 *               </restriction>
 *             </complexContent>
 *           </complexType>
 *         </element>
 *       </sequence>
 *       <attribute name="uuid" type="{http://www.cisco.com/AXL/API/8.0}XUUID" />
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RUnitsToGateway", propOrder = {
    "domainName",
    "gatewayUuid",
    "units"
})
public class RUnitsToGateway {

    protected String domainName;
    protected String gatewayUuid;
    protected RUnitsToGateway.Units units;
    @XmlAttribute
    protected String uuid;

    /**
     * Gets the value of the domainName property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getDomainName() {
        return domainName;
    }

    /**
     * Sets the value of the domainName property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setDomainName(String value) {
        this.domainName = value;
    }

    /**
     * Gets the value of the gatewayUuid property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getGatewayUuid() {
        return gatewayUuid;
    }

    /**
     * Sets the value of the gatewayUuid property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setGatewayUuid(String value) {
        this.gatewayUuid = value;
    }

    /**
     * Gets the value of the units property.
     *
     * @return
     *     possible object is
     *     {@link RUnitsToGateway.Units }
     *
     */
    public RUnitsToGateway.Units getUnits() {
        return units;
    }

    /**
     * Sets the value of the units property.
     *
     * @param value
     *     allowed object is
     *     {@link RUnitsToGateway.Units }
     *
     */
    public void setUnits(RUnitsToGateway.Units value) {
        this.units = value;
    }

    /**
     * Gets the value of the uuid property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getUuid() {
        return uuid;
    }

    /**
     * Sets the value of the uuid property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setUuid(String value) {
        this.uuid = value;
    }

    /**
     *
Java class for anonymous complex type.
     *
     *
The following schema fragment specifies the expected content contained within this class.
     *
     *

     * <complexType>
     *   <complexContent>
     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       <sequence minOccurs="0">
     *         <element name="unit" maxOccurs="unbounded" minOccurs="0">
     *           <complexType>
     *             <complexContent>
     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *                 <sequence minOccurs="0">
     *                   <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
     *                   <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPSlotModule" minOccurs="0"/>
     *                   <element name="subunits" minOccurs="0">
     *                     <complexType>
     *                       <complexContent>
     *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *                           <sequence minOccurs="0">
     *                             <element name="subunit" maxOccurs="unbounded" minOccurs="0">
     *                               <complexType>
     *                                 <complexContent>
     *                                   <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *                                     <sequence minOccurs="0">
     *                                       <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
     *                                       <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPVic" minOccurs="0"/>
     *                                       <element name="beginPort" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
     *                                     </sequence>
     *                                   </restriction>
     *                                 </complexContent>
     *                               </complexType>
     *                             </element>
     *                           </sequence>
     *                         </restriction>
     *                       </complexContent>
     *                     </complexType>
     *                   </element>
     *                 </sequence>
     *               </restriction>
     *             </complexContent>
     *           </complexType>
     *         </element>
     *       </sequence>
     *     </restriction>
     *   </complexContent>
     * </complexType>
     *

     *
     *
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "unit"
    })
    public static class Units {

        protected List<RUnitsToGateway.Units.Unit> unit;

        /**
         * Gets the value of the unit property.
         *
         *

         * This accessor method returns a reference to the live list,
         * not a snapshot. Therefore any modification you make to the
         * returned list will be present inside the JAXB object.
         * This is why there is not a set method for the unit property.
         *
         *

         * For example, to add a new item, do as follows:
         *

         *    getUnit().add(newItem);
         *

         *
         *
         *

         * Objects of the following type(s) are allowed in the list
         * {@link RUnitsToGateway.Units.Unit }
         *
         *
         */
        public List<RUnitsToGateway.Units.Unit> getUnit() {
            if (unit == null) {
                unit = new ArrayList<RUnitsToGateway.Units.Unit>();
            }
            return this.unit;
        }

        /**
         *
Java class for anonymous complex type.
         *
         *
The following schema fragment specifies the expected content contained within this class.
         *
         *

         * <complexType>
         *   <complexContent>
         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
         *       <sequence minOccurs="0">
         *         <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
         *         <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPSlotModule" minOccurs="0"/>
         *         <element name="subunits" minOccurs="0">
         *           <complexType>
         *             <complexContent>
         *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
         *                 <sequence minOccurs="0">
         *                   <element name="subunit" maxOccurs="unbounded" minOccurs="0">
         *                     <complexType>
         *                       <complexContent>
         *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
         *                           <sequence minOccurs="0">
         *                             <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
         *                             <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPVic" minOccurs="0"/>
         *                             <element name="beginPort" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
         *                           </sequence>
         *                         </restriction>
         *                       </complexContent>
         *                     </complexType>
         *                   </element>
         *                 </sequence>
         *               </restriction>
         *             </complexContent>
         *           </complexType>
         *         </element>
         *       </sequence>
         *     </restriction>
         *   </complexContent>
         * </complexType>
         *

         *
         *
         */
        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {
            "index",
            "product",
            "subunits"
        })
        public static class Unit {

            protected String index;
            protected String product;
            protected RUnitsToGateway.Units.Unit.Subunits subunits;

            /**
             * Gets the value of the index property.
             *
             * @return
             *     possible object is
             *     {@link String }
             *
             */
            public String getIndex() {
                return index;
            }

            /**
             * Sets the value of the index property.
             *
             * @param value
             *     allowed object is
             *     {@link String }
             *
             */
            public void setIndex(String value) {
                this.index = value;
            }

            /**
             * Gets the value of the product property.
             *
             * @return
             *     possible object is
             *     {@link String }
             *
             */
            public String getProduct() {
                return product;
            }

            /**
             * Sets the value of the product property.
             *
             * @param value
             *     allowed object is
             *     {@link String }
             *
             */
            public void setProduct(String value) {
                this.product = value;
            }

            /**
             * Gets the value of the subunits property.
             *
             * @return
             *     possible object is
             *     {@link RUnitsToGateway.Units.Unit.Subunits }
             *
             */
            public RUnitsToGateway.Units.Unit.Subunits getSubunits() {
                return subunits;
            }

            /**
             * Sets the value of the subunits property.
             *
             * @param value
             *     allowed object is
             *     {@link RUnitsToGateway.Units.Unit.Subunits }
             *
             */
            public void setSubunits(RUnitsToGateway.Units.Unit.Subunits value) {
                this.subunits = value;
            }

            /**
             *
Java class for anonymous complex type.
             *
             *
The following schema fragment specifies the expected content contained within this class.
             *
             *

             * <complexType>
             *   <complexContent>
             *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
             *       <sequence minOccurs="0">
             *         <element name="subunit" maxOccurs="unbounded" minOccurs="0">
             *           <complexType>
             *             <complexContent>
             *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
             *                 <sequence minOccurs="0">
             *                   <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
             *                   <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPVic" minOccurs="0"/>
             *                   <element name="beginPort" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
             *                 </sequence>
             *               </restriction>
             *             </complexContent>
             *           </complexType>
             *         </element>
             *       </sequence>
             *     </restriction>
             *   </complexContent>
             * </complexType>
             *

             *
             *
             */
            @XmlAccessorType(XmlAccessType.FIELD)
            @XmlType(name = "", propOrder = {
                "subunit"
            })
            public static class Subunits {

                protected List<RUnitsToGateway.Units.Unit.Subunits.Subunit> subunit;

                /**
                 * Gets the value of the subunit property.
                 *
                 *

                 * This accessor method returns a reference to the live list,
                 * not a snapshot. Therefore any modification you make to the
                 * returned list will be present inside the JAXB object.
                 * This is why there is not a set method for the subunit property.
                 *
                 *

                 * For example, to add a new item, do as follows:
                 *

                 *    getSubunit().add(newItem);
                 *

                 *
                 *
                 *

                 * Objects of the following type(s) are allowed in the list
                 * {@link RUnitsToGateway.Units.Unit.Subunits.Subunit }
                 *
                 *
                 */
                public List<RUnitsToGateway.Units.Unit.Subunits.Subunit> getSubunit() {
                    if (subunit == null) {
                        subunit = new ArrayList<RUnitsToGateway.Units.Unit.Subunits.Subunit>();
                    }
                    return this.subunit;
                }

                /**
                 *
Java class for anonymous complex type.
                 *
                 *
The following schema fragment specifies the expected content contained within this class.
                 *
                 *

                 * <complexType>
                 *   <complexContent>
                 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
                 *       <sequence minOccurs="0">
                 *         <element name="index" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
                 *         <element name="product" type="{http://www.cisco.com/AXL/API/8.0}XMGCPVic" minOccurs="0"/>
                 *         <element name="beginPort" type="{http://www.cisco.com/AXL/API/8.0}XInteger" minOccurs="0"/>
                 *       </sequence>
                 *     </restriction>
                 *   </complexContent>
                 * </complexType>
                 *

                 *
                 *
                 */
                @XmlAccessorType(XmlAccessType.FIELD)
                @XmlType(name = "", propOrder = {
                    "index",
                    "product",
                    "beginPort"
                })
                public static class Subunit {

                    protected String index;
                    protected String product;
                    protected String beginPort;

                    /**
                     * Gets the value of the index property.
                     *
                     * @return
                     *     possible object is
                     *     {@link String }
                     *
                     */
                    public String getIndex() {
                        return index;
                    }

                    /**
                     * Sets the value of the index property.
                     *
                     * @param value
                     *     allowed object is
                     *     {@link String }
                     *
                     */
                    public void setIndex(String value) {
                        this.index = value;
                    }

                    /**
                     * Gets the value of the product property.
                     *
                     * @return
                     *     possible object is
                     *     {@link String }
                     *
                     */
                    public String getProduct() {
                        return product;
                    }

                    /**
                     * Sets the value of the product property.
                     *
                     * @param value
                     *     allowed object is
                     *     {@link String }
                     *
                     */
                    public void setProduct(String value) {
                        this.product = value;
                    }

                    /**
                     * Gets the value of the beginPort property.
                     *
                     * @return
                     *     possible object is
                     *     {@link String }
                     *
                     */
                    public String getBeginPort() {
                        return beginPort;
                    }

                    /**
                     * Sets the value of the beginPort property.
                     *
                     * @param value
                     *     allowed object is
                     *     {@link String }
                     *
                     */
                    public void setBeginPort(String value) {
                        this.beginPort = value;
                    }

                }

            }

        }

    }

}


text:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using Dapper.FluentMap;
using Dapper.FluentMap.Dommel;
using Dommel;
using Npgsql;
using YuGiOh.Common.DatabaseMappers;
using YuGiOh.Common.Extensions;
using YuGiOh.Common.Interfaces;
using YuGiOh.Common.Models.YuGiOh;
using YuGiOh.Common.Repositories.Interfaces;

// Although Dapper auto-opens/closes connections that call it when it wasn't opened when called upon, I rather open it myself for consistency
// Not using CloseAsync() because Dispose() automatically calls it
// Theoretically.....
// Hopefully........
// Please close it..... don't make me look stupid

namespace YuGiOh.Common.Repositories
{
    public class YuGiOhRepository : IYuGiOhRepository
    {

        // private const string EscapeSqlParameterRegex = @"([%_\[])";
        // private const string ReplaceEscapeSqlParameterRegex = "[$1]";

        private readonly IYuGiOhRepositoryConfiguration _config;

        static YuGiOhRepository()
        {

            FluentMapper.Initialize(config =>
            {

                config
                    .AddConvention<LowerCaseConvention>()
                    .ForEntity<CardEntity>()
                    .ForEntity<BoosterPackEntity>();

                config.AddMap(new CardEntityMapper());
                config.AddMap(new BoosterPackEntityMapper());
                config.ForDommel();

                var resolver = new LowerCaseConvention();

                DommelMapper.SetColumnNameResolver(resolver);
                DommelMapper.AddSqlBuilder(typeof(NpgsqlConnection), new PostgresSqlBuilder());

            });

        }

        public YuGiOhRepository(IYuGiOhRepositoryConfiguration config)
        {
            _config = config;
        }

        #region Insertions

        public async Task InsertCardAsync(CardEntity card)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var doesExistBit = await connection.ExecuteScalarAsync<int>("select count(1) from cards where id = @Id", new { card.Id }).ConfigureAwait(false);

            if (doesExistBit == 1)
                await connection.UpdateAsync(card).ConfigureAwait(false);
            else
                await connection.InsertAsync(card).ConfigureAwait(false);

            // var (cardArchetypesId, cardSupportsId, cardAntiSupportsId) = await connection.ExecuteScalarAsync<(int, int, int)>("select archetypes, supports, antisupports from cards where id = @id", new { id = card.Id });

            if (card.Translations is not null && card.Translations.Any())
            {

                foreach (var translation in card.Translations)
                {

                    translation.CardId = card.Id;

                    await connection.ExecuteAsync(
                            "upsert_translation",
                            new
                            {
                                cardid = translation.CardId,
                                language = translation.Language,
                                name = translation.Name,
                                lore = translation.Lore
                            },
                            commandType: CommandType.StoredProcedure
                        )
                        .ConfigureAwait(false);

                }

            }

            if (card.Archetypes is not null && card.Archetypes.Any())
            {

                var archetypes = card.Archetypes.Where(archetype => !string.IsNullOrEmpty(archetype));
                var archetypesInDb = await connection
                    .QueryAsync<string>("select distinct archetypename from joined_cards where id = @id", new { id = card.Id })
                    .ContinueWith(result => result.Result.ToArray())
                    .ConfigureAwait(false);
                var archetypesToDelete = archetypesInDb.Where(archetype => !archetypes.Contains(archetype));
                var archetypesToInsert = archetypes.Where(archetype => !archetypesInDb.Contains(archetype));

                foreach (var archetype in archetypesToDelete)
                    await connection.ExecuteAsync("call delete_archetype_relation(@cardname, @archetype)", new { cardname = card.Name, archetype }).ConfigureAwait(false);

                foreach (var archetype in archetypesToInsert)
                    await connection.ExecuteAsync("call insert_archetype_relation(@cardname, @archetype)", new { cardname = card.Name, archetype }).ConfigureAwait(false);

            }

            if (card.Supports is not null && card.Supports.Any())
            {

                var supports = card.Supports.Where(support => !string.IsNullOrEmpty(support));
                var supportsInDb = await connection
                    .QueryAsync<string>("select distinct supportname from joined_cards where id = @id", new { id = card.Id })
                    .ContinueWith(result => result.Result.ToArray())
                    .ConfigureAwait(false);
                var supportsToDelete = supportsInDb.Where(support => !supports.Contains(support));
                var supportsToInsert = supports.Where(support => !supportsInDb.Contains(support));

                foreach (var support in supportsToDelete)
                    await connection.ExecuteAsync("call delete_support_relation(@cardname, @support)", new { cardname = card.Name, support }).ConfigureAwait(false);

                foreach (var support in supportsToInsert)
                    await connection.ExecuteAsync("call insert_support_relation(@cardname, @support)", new { cardname = card.Name, support }).ConfigureAwait(false);

            }

            if (card.AntiSupports is not null && card.AntiSupports.Any())
            {

                var antisupports = card.AntiSupports.Where(antisupport => !string.IsNullOrEmpty(antisupport));
                var antisupportsInDb = await connection
                    .QueryAsync<string>("select distinct antisupportname from joined_cards where id = @id", new { id = card.Id })
                    .ContinueWith(result => result.Result.ToArray())
                    .ConfigureAwait(false);
                var antisupportsToDelete = antisupportsInDb.Where(antisupport => !antisupports.Contains(antisupport));
                var antisupportsToInsert = antisupports.Where(antisupport => !antisupportsInDb.Contains(antisupport));

                foreach (var antisupport in antisupportsToDelete)
                    await connection.ExecuteAsync("call delete_antisupport_relation(@cardname, @antisupport)", new { cardname = card.Name, antisupport }).ConfigureAwait(false);

                foreach (var antisupport in antisupportsToInsert)
                    await connection.ExecuteAsync("call insert_antisupport_relation(@cardname, @antisupport)", new { cardname = card.Name, antisupport }).ConfigureAwait(false);

            }

        }

        public async Task InsertCardHashAsync(int id, string hash)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);
            await connection.ExecuteAsync("insert into card_hashes values(@id, @hash) on conflict on constraint card_hashes_pkey do update set hash = @hash", new { id, hash }).ConfigureAwait(false);

        }

        public async Task InsertBoosterPack(BoosterPackEntity boosterPack)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var doesExistBit = await connection.ExecuteScalarAsync<int>("select count(1) from boosterpacks where id = @Id", new { boosterPack.Id }).ConfigureAwait(false);

            if (doesExistBit == 1)
                await connection.UpdateAsync(boosterPack).ConfigureAwait(false);
            else
                await connection.InsertAsync(boosterPack).ConfigureAwait(false);

            var (datesId, cardsId) = await connection.QuerySingleAsync<(int, int)>("select dates, cards from boosterpacks where id = @id", new { id = boosterPack.Id }).ConfigureAwait(false);
            // var datesId = await connection.QuerySingleAsync<int>("select dates from boosterpacks where id = @id", new { id = boosterPack.Id }).ConfigureAwait(false);
            // var cardsId = await connection.QuerySingleAsync<int>("select cards from boosterpacks where id = @id", new { id = boosterPack.Id }).ConfigureAwait(false);

            foreach (var date in boosterPack.Dates)
            {

                date.BoosterPackDatesId = datesId;

                await connection.ExecuteAsync(
                        "upsert_boosterpack_date",
                        new
                        {
                            boosterpackdatesid = date.BoosterPackDatesId,
                            name = date.Name,
                            date = date.Date
                        },
                        commandType: CommandType.StoredProcedure)
                    .ConfigureAwait(false);

            }

            foreach (var card in boosterPack.Cards)
            {

                card.BoosterPackCardsId = cardsId;

                card.Id = await connection.QuerySingleAsync<int>(
                        "insert_or_get_boosterpack_card",
                        new
                        {
                            _boosterpackcardsid = card.BoosterPackCardsId,
                            _name = card.Name
                        },
                        commandType: CommandType.StoredProcedure)
                    .ConfigureAwait(false);

                var raritiesId = await connection.QuerySingleAsync<int>("select rarities from boosterpack_cards where id = @id", new { id = card.Id }).ConfigureAwait(false);

                foreach (var rarity in card.Rarities)
                {

                    await connection.ExecuteAsync(
                            "insert into boosterpack_rarities(boosterpackraritiesid, name) values(@boosterpackraritiesid, @name) on conflict on constraint boosterpack_rarities_boosterpackraritiesid_name_unique_pair do nothing",
                            new
                            {
                                boosterpackraritiesid = raritiesId,
                                name = rarity
                            })
                        .ConfigureAwait(false);

                }

            }

        }

        public async Task InsertErrorAsync(Error error)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);
            await connection.InsertAsync(error).ConfigureAwait(false);

        }

        #endregion Insertions

        public async Task<string> GetCardHashAsync(int id)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var serverHash = await connection.QueryFirstOrDefaultAsync<string>("select hash from card_hashes where id = @id", new { id }).ConfigureAwait(false);

            return serverHash?.Trim();

        }

        #region CardEntity Queries

        public async Task<CardEntity> GetCardAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var card = await connection.QuerySingleCardProcAsync("get_card_exact", new { input }).ConfigureAwait(false);

            return card;

        }

        public async Task<IEnumerable<CardEntity>> SearchCardsAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var cards = await connection.QueryCardsProcAsync("search_cards", new { input }).ConfigureAwait(false);

            return cards;

        }

        public async Task<IEnumerable<CardEntity>> GetCardsContainsAllAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var inputWords = input.Split(' ');
            //var results = await connection.SelectAsync<CardEntity>(card =>
            //    inputWords.All(word => card.Name.ContainsIgnoreCase(word))
            //);

            var sqlBuilder = new SqlBuilder();
            var selector = sqlBuilder.AddTemplate("select * from joined_cards /**where**/ order by char_length(name)");
            var parameters = new DynamicParameters();

            for (var i = 0; i < inputWords.Length; i++)
            {

                var key = $"@{i}";

                sqlBuilder.Where($"name ilike {key}");
                parameters.Add(key, $"%{inputWords[i]}%");

            }

            var cards = await connection.QueryCardsAsync(selector.RawSql, parameters).ConfigureAwait(false);

            return cards;

        }

        public async Task<CardEntity> GetCardFuzzyAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var card = await connection.QuerySingleCardProcAsync("get_card_fuzzy", new { input }).ConfigureAwait(false);

            return card;

        }

        public async Task<CardEntity> GetRandomCardAsync()
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var card = await connection.QuerySingleCardProcAsync("get_random_card").ConfigureAwait(false);

            return card;

        }

        public async Task<IEnumerable<CardEntity>> GetCardsInArchetypeAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var cards = await connection.QueryCardsProcAsync("get_cards_in_archetype", new { input }).ConfigureAwait(false);

            return cards;

        }

        public async Task<IEnumerable<CardEntity>> GetCardsInSupportAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var cards = await connection.QueryCardsProcAsync("get_cards_in_support", new { input }).ConfigureAwait(false);

            return cards;

        }

        public async Task<IEnumerable<CardEntity>> GetCardsInAntisupportAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var cards = await connection.QueryCardsProcAsync("get_cards_in_antisupport", new { input }).ConfigureAwait(false);

            return cards;

        }

        #endregion CardEntity Queries

        #region Autocomplete Queries

        public async Task<IEnumerable<string>> GetCardsAutocompleteAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var cards = await connection.QueryProcAsync<string>("get_cards_autocomplete", new { input }).ConfigureAwait(false);

            return cards;

        }

        public async Task<IEnumerable<string>> GetArchetypesAutocompleteAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var archetypes = await connection.QueryProcAsync<string>("get_archetypes_autocomplete", new { input }).ConfigureAwait(false);

            return archetypes;

        }

        public async Task<IEnumerable<string>> GetSupportsAutocompleteAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var supports = await connection.QueryProcAsync<string>("get_supports_autocomplete", new { input }).ConfigureAwait(false);

            return supports;

        }

        public async Task<IEnumerable<string>> GetAntisupportsAutocompleteAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var antisupports = await connection.QueryProcAsync<string>("get_antisupports_autocomplete", new { input }).ConfigureAwait(false);

            return antisupports;

        }

        #endregion Autocomplete Queries

        public async Task<string> GetNameWithPasscodeAsync(string passcode)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var name = await connection.ExecuteScalarAsync<string>("select name from cards where passcode = @passcode", new { passcode }).ConfigureAwait(false);

            return name;

        }

        public async Task<string> GetImageLinkAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var imgLink = await connection.QuerySingleAsync<string>("select img from cards where name ~~* @input", new { input }).ConfigureAwait(false);

            return imgLink;

        }

        public async Task<Banlist> GetBanlistAsync(BanlistFormats format)
        {

            var formatStr = format switch
            {

                BanlistFormats.OCG => "ocgstatus",
                BanlistFormats.TCG => "tcgadvstatus",
                BanlistFormats.TRAD => "tcgtrnstatus",
                _ => null

            };

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            var banlist = new Banlist
            {
                Forbidden = await connection.QueryAsync<string>($"select name from cards where {formatStr} ilike 'forbidden' order by name asc").ConfigureAwait(false),
                Limited = await connection.QueryAsync<string>($"select name from cards where {formatStr} ilike 'limited' order by name asc").ConfigureAwait(false),
                SemiLimited = await connection.QueryAsync<string>($"select name from cards where {formatStr} ilike 'semi-limited' order by name asc").ConfigureAwait(false)
            };

            return banlist;

        }

        public async Task<BoosterPackEntity> GetBoosterPackAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync().ConfigureAwait(false);

            BoosterPackEntity entity = null;
            var dateEntityDict = new Dictionary<string, BoosterPackDateEntity>();
            var cardEntityDict = new Dictionary<string, BoosterPackCardEntity>();

            await connection.QueryAsync<BoosterPackEntity, BoosterPackDateEntity, BoosterPackCardEntity, string, BoosterPackEntity>(
                    "select * from joined_boosterpacks where name ilike @input",
                    (
                        boosterpackEntity,
                        dateEntity,
                        cardEntity,
                        rarity
                    ) =>
                    {

                        if (entity is null)
                        {

                            entity = boosterpackEntity;
                            entity.Cards = new List<BoosterPackCardEntity>();
                            entity.Dates = new List<BoosterPackDateEntity>();

                        }

                        if (!dateEntityDict.TryGetValue(dateEntity.Name, out var dateBpEntity))
                        {

                            dateBpEntity = dateEntity;

                            dateEntityDict[dateEntity.Name] = dateBpEntity;

                        }

                        if (!cardEntityDict.TryGetValue(cardEntity.Name, out var cardBpEntity))
                        {

                            cardBpEntity = cardEntity;
                            cardBpEntity.Rarities = new List<string>();
                            cardEntityDict[cardBpEntity.Name] = cardBpEntity;

                        }

                        if (!entity.Dates.Contains(dateBpEntity))
                            entity.Dates.Add(dateBpEntity);

                        if (!entity.Cards.Contains(cardBpEntity))
                            entity.Cards.Add(cardBpEntity);

                        if (!cardBpEntity.Rarities.Contains(rarity))
                            cardBpEntity.Rarities.Add(rarity);

                        return entity;

                    },
                    new { input },
                    splitOn: "boosterpackdatename,boosterpackcardname,boosterpackrarity"
                )
                .ConfigureAwait(false);

            return entity;

        }

        public async Task<IEnumerable<string>> GetBoosterPacksAutocompleteAsync(string input)
        {

            await using var connection = _config.GetYuGiOhDbConnection();

            await connection.OpenAsync();

            var boosterpacks = await connection.QueryAsync<string>("get_boosterpacks_autocomplete", new { input }, commandType: CommandType.StoredProcedure);

            return boosterpacks;

        }

    }
}

redpajama_set_name: RedPajamaGithub


text:
module Guesswork.Math.Statistics where

import qualified Data.Vector.Unboxed as VU
import Guesswork.Types

kh xs = sqrt . (/n) . sum . map (\x->(x-avg')**2) $ xs
  where avg' = avg xs
        n    = fromIntegral . length $ xs

avg [] = error "Empty list!"
avg xs = sum xs / (fromIntegral . length $ xs)

euclidianNorm :: FeatureVector -> FeatureVector -> Double
euclidianNorm u v = VU.sum $ VU.zipWith (\a b -> (a - b)**2) u v

-- |Scales lists (truths, predictions) between [0,1] using
-- scales from truths.
-- NOTE: this means that all predictions aren't necessarily
-- between [0,1].
scaleLists truths preds =
    let minT  = minimum truths
        maxT  = maximum truths
        scale = map ((/ maxT) . subtract minT)
    in (scale truths, scale preds)

-- |Calculate population variance.
popVariance :: [Double] -> Double
popVariance xs =
  let n  = fromIntegral . length $ xs
      ax = avg xs
  in (*(1/n)) . sum . map ((**2) . subtract ax) $ xs

-- |Pearson's sample correlation. Correlation is in range
-- [-1,1] and is 1.0 if lists are identical.
-- List aren't checked to be of same length.
sampleCorrelation :: [Double] -> [Double] -> Double
sampleCorrelation xs ys
    | length xs < 2 || length ys < 2 = error "Correlation: too short lists."
    | otherwise                      = if xs == ys then 1.0 else corr
  where
    avgX   = avg xs
    avgY   = avg ys
    nxs    = map (subtract avgX) xs
    nys    = map (subtract avgY) ys
    upper  = sum $ zipWith (*) nxs nys
    lowerX = sum $ map (**2) nxs
    lowerY = sum $ map (**2) nys
    lower  = sqrt $ lowerX * lowerY
    corr   = upper / lower

-- |Calculate root mean square error from given list of
-- truths and predictions.
rmse :: [Double] -> [Double] -> Double
rmse truths preds =
    let errors = sum . map (**2) $ zipWith (-) truths preds
        n      = fromIntegral . length $ truths
    in sqrt $ errors / n


text:
package slack

import (
	"context"
	"encoding/json"
	"fmt"
	"net/url"
	"time"
)

// StartRTM calls the "rtm.start" endpoint and returns the provided URL and the full Info block.
//
// To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
func (api *Client) StartRTM() (info *Info, websocketURL string, err error) {
	return api.StartRTMContext(context.Background())
}

// StartRTMContext calls the "rtm.start" endpoint and returns the provided URL and the full Info block with a custom context.
//
// To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
func (api *Client) StartRTMContext(ctx context.Context) (info *Info, websocketURL string, err error) {
	response := &infoResponseFull{}
	err = post(ctx, "rtm.start", url.Values{"token": {api.config.token}}, response, api.debug)
	if err != nil {
		return nil, "", fmt.Errorf("post: %s", err)
	}
	if !response.Ok {
		return nil, "", response.Error
	}

	// websocket.Dial does not accept url without the port (yet)
	// Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3
	// but slack returns the address with no port, so we have to fix it
	api.Debugln("Using URL:", response.Info.URL)
	websocketURL, err = websocketizeURLPort(response.Info.URL)
	if err != nil {
		return nil, "", fmt.Errorf("parsing response URL: %s", err)
	}

	return &response.Info, websocketURL, nil
}

// ConnectRTM calls the "rtm.connect" endpoint and returns the provided URL and the compact Info block.
//
// To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
func (api *Client) ConnectRTM() (info *Info, websocketURL string, err error) {
	return api.ConnectRTMContext(context.Background())
}

// ConnectRTM calls the "rtm.connect" endpoint and returns the provided URL and the compact Info block with a custom context.
//
// To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it.
func (api *Client) ConnectRTMContext(ctx context.Context) (info *Info, websocketURL string, err error) {
	response := &infoResponseFull{}
	err = post(ctx, "rtm.connect", url.Values{"token": {api.config.token}}, response, api.debug)
	if err != nil {
		return nil, "", fmt.Errorf("post: %s", err)
	}
	if !response.Ok {
		return nil, "", response.Error
	}

	// websocket.Dial does not accept url without the port (yet)
	// Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3
	// but slack returns the address with no port, so we have to fix it
	api.Debugln("Using URL:", response.Info.URL)
	websocketURL, err = websocketizeURLPort(response.Info.URL)
	if err != nil {
		return nil, "", fmt.Errorf("parsing response URL: %s", err)
	}

	return &response.Info, websocketURL, nil
}

// NewRTM returns a RTM, which provides a fully managed connection to
// Slack's websocket-based Real-Time Messaging protocol.
func (api *Client) NewRTM() *RTM {
	return api.NewRTMWithOptions(nil)
}

// NewRTMWithOptions returns a RTM, which provides a fully managed connection to
// Slack's websocket-based Real-Time Messaging protocol.
// This also allows to configure various options available for RTM API.
func (api *Client) NewRTMWithOptions(options *RTMOptions) *RTM {
	result := &RTM{
		Client:           *api,
		IncomingEvents:   make(chan RTMEvent, 50),
		outgoingMessages: make(chan OutgoingMessage, 20),
		pings:            make(map[int]time.Time),
		isConnected:      false,
		wasIntentional:   true,
		killChannel:      make(chan bool),
		forcePing:        make(chan bool),
		rawEvents:        make(chan json.RawMessage),
		idGen:            NewSafeID(1),
	}

	if options != nil {
		result.useRTMStart = options.UseRTMStart
	} else {
		result.useRTMStart = true
	}

	return result
}


text:
describe Starwars::Cursor do
  let(:resource) { Starwars::Planet }
  let(:uri) { 'http://swapi.co/api/planets/' }
  let(:as) { Starwars::Request::FORMAT }
  let(:params) { { two: 2 } }
  let(:method) { :get }
  let(:cursor) do
    Starwars::Cursor.new
  end

  describe '#last_page?' do
    it 'returns true if so' do
      cursor.next = nil
      expect(cursor.last_page?).to eq(true)
    end

    it 'returns false if not' do
      cursor.next = '/something'
      expect(cursor.last_page?).to eq(false)
    end
  end

  describe '#next_page?' do
    it 'returns true if so' do
      cursor.next = '/something'
      expect(cursor.next_page?).to eq(true)
    end

    it 'returns false if not' do
      cursor.next = nil
      expect(cursor.next_page?).to eq(false)
    end
  end

  describe '#next_page' do
    let(:request_response) do
      double(body: { results: [], next: '/something', pervious: nil })
    end
    before :each do
      allow(cursor).to receive(:perform_request).and_return(request_response)
    end

    it 'returns nil if there are no more pages' do
      cursor.next = nil
      expect(cursor.next_page).to eq(nil)
    end

    it 'performs a request' do
      cursor.next = 'http://swapi.co/api/planets/?page=2'
      expect(cursor).to receive(:perform_request)
      cursor.next_page
    end
  end

  describe '#each_page' do
    it 'should return an enumerator if no block is provided' do
      expect(cursor.each_page).to be_an(Enumerator)
    end

    it 'yields till no more pages' do
      request_responses = [
        double(body: { previous: nil, results: [1, 2, 3, 4] }),
        double(body: { next: '/next/next', previous: '/previous', results: [1, 2, 3, 4] }),
        double(body: { next: nil, previous: '/previous', results: [1, 2, 3, 4] })
      ]
      cursor.next = '/something'
      allow(cursor).to receive(:perform_request).and_return(request_responses[0])
      expect(cursor).to receive(:perform_request).exactly(4).times

      cursor.each_with_index do |_, index|
        allow(cursor).to receive(:perform_request).and_return(request_responses[index])
        cursor.next = request_responses[index]
      end
    end
  end
end


text:
// Copyright 2012-2013 Andreas Louca <andreas@louca.org>. All rights reserved.
// Use of this source code is governed by the 2-clause BSD license
// license that can be found in the LICENSE file.

/*
Package mongoqueue provides a job queue, which uses Mongo as a backend storage engine.
It supports a sophisticated feature set,  facilitating fine-grained job queueing.

See: https://github.com/alouca/MongoQueue
*/

package mongoqueue

import (
	"code.google.com/p/go-uuid/uuid"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"time"
)

type MongoScheduleJobs struct {
	MongoSession *mgo.Session
	Database     string
}

func NewMongoScheduleJobs(database, server string) (*MongoScheduleJobs, error) {
	var err error
	msj := new(MongoScheduleJobs)
	msj.MongoSession, err = mgo.Dial(server)
	if err != nil {
		return nil, err
	}
	msj.Database = database

	go msj.Start()

	return msj, nil
}

func (m *MongoScheduleJobs) ScheduleJob(name string, queue string, x interface{}, p int, interval int64) {
	coll := m.MongoSession.DB(m.Database).C("mongoschedulejobs")

	coll.Insert(bson.M{
		"name":     name,
		"queue":    queue,
		"next-run": time.Now().Unix(),
		"priority": p,
		"interval": interval,
		"data":     x,
	})
}

func (m *MongoScheduleJobs) DeleteJob(name string) {
	coll := m.MongoSession.DB(m.Database).C("mongoschedulejobs")

	coll.Remove(bson.M{"name": name})
}

func (m *MongoScheduleJobs) Start() {
	t := time.NewTicker(time.Second * 10)
	coll := m.MongoSession.DB(m.Database).C("mongoschedulejobs")

	for {
		select {
		case <-t.C:
			now := time.Now().Unix()

			q := coll.Find(bson.M{"next-run": bson.M{"$lte": now}}).Iter()

			var res bson.M

			for q.Next(&res) {
				l.Info("Adding job for execution in queue %s\n", res["queue"])
				// Queue the job
				m.addJob(res["queue"].(string), res["data"], res["priority"].(int))

				// Set next-run
				coll.Update(bson.M{"_id": res["_id"]}, bson.M{"$set": bson.M{"next-run": now + res["interval"].(int64)}})
			}

		}

	}
}

func (m *MongoScheduleJobs) addJob(queue string, x interface{}, p int) (string, error) {
	coll := m.MongoSession.DB(m.Database).C(queue)

	id := uuid.NewRandom().String()

	now := time.Now().Unix()
	err := coll.Insert(bson.M{
		"id":         id,
		"inprogress": false,
		"failed":     false,
		"priority":   p,
		"retries":    0,
		"added":      now,
		"runat":      now,
		"data":       x})

	if err != nil {
		l.Fatal("Error inserting new task: %s\n", err.Error())
	}

	return id, err

}


text:
require 'sugarcrm/associations/association'
require 'sugarcrm/associations/associations'
require 'sugarcrm/associations/association_cache'
require 'sugarcrm/associations/association_methods'
require 'sugarcrm/associations/association_collection'


text:
package org.wikiup.servlet.impl.context.env;

import org.wikiup.core.impl.iterable.BeanPropertyNames;
import org.wikiup.core.impl.iterable.IterableCollection;
import org.wikiup.core.inf.Dictionary;
import org.wikiup.core.util.Dictionaries;
import org.wikiup.servlet.ServletProcessorContext;
import org.wikiup.servlet.inf.ServletProcessorContextAware;

import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;

public class Request implements Dictionary<Object>, ServletProcessorContextAware, Iterable<String> {
    private ServletProcessorContext context;

    public void setServletProcessorContext(ServletProcessorContext context) {
        this.context = context;
    }

    public Object get(String name) {
        Object obj = Dictionaries.getBeanProperty(this, name);
        return obj != null ? obj : Dictionaries.getBeanProperty(context.getServletRequest(), name);
    }

    public Iterator<String> iterator() {
        IterableCollection<String> ci = new IterableCollection<String>(new BeanPropertyNames(this.getClass()));
        ci.append(new BeanPropertyNames(HttpServletRequest.class));
        return ci.iterator();
    }

    public Dictionary<String> getHeaders() {
        return new Dictionary<String>() {
            public String get(String name) {
                return context.getHeader(name);
            }
        };
    }
}


text:
package com.streamer.twitter

import java.io.InputStream

/**
 * StreamProcessor
 *
 * In order to process the stream of tweets, you have to concretely define
 * on your subclass what to do with the InputStream
 */
abstract class StreamProcessor {

  // This method customizes the handling of the stream
  def process(is: InputStream): Unit
}


text:
.. _station_auto:

Weather stations
================

.. automodule:: cloudside.station
   :members:
   :undoc-members:
   :show-inheritance:


text:
DIR="$( cd "$( dirname "$0" )" && pwd )"
cd ${DIR}/../../

rm -f uri_dump;

# Enable logging in config
sed 's/dump_test_uris:\ false/dump_test_uris:\ true/' config.test.yaml > temp.config.test.yaml
export RB_TEST_CONFIG=${DIR}/../../temp.config.test.yaml

# Run tests
sh $DIR/run_tests.sh test sqlite

# Remove duplicates
sort -u -o uri_dump.tmp uri_dump; mv uri_dump.tmp uri_dump

# Delete URIs exposed only for tests
sed -i.bak '/\/buckets\//d' uri_dump
sed -i.bak '/foobar\.com/d' uri_dump
sed -i.bak '/^\/$/d' uri_dump
sed -i.bak '/fr\.wikipedia\.org/d' uri_dump
sed -i.bak '/test\.wikipedia\.org/d' uri_dump
sed -i.bak '/test2\.wikipedia\.org/d' uri_dump
sed -i.bak '/User:Pchelolo\/Access_Check_Tests/d' uri_dump

# Rewrite to the /api/rest_v1/ form
sed -i.bak 's/^\/\([[:alnum:]\.]*\)\/v1/https:\/\/\1\/api\/rest_v1/' uri_dump

# Report and clean up.
echo "Collected uris: `cat uri_dump | wc -l`"
echo "The list of URIs could be found in 'uri_dump' file"
rm -f temp.config.test.yaml uri_dump.bak


text:
var Luc = require('luc'),
    exports = {
        Runner: require('./runner'),
        Interceptor: require('./interceptor'),
        Watcher: require('./watcher')
    };
Luc.addSubmodule('devUtils', exports);

module.exports = exports;


text:
using System;
using System.Collections.Generic;

namespace CavemanTools.Special
{
	/// <summary>
	/// Agregates values from different sources for an option.
	/// THe priority strategy selects the final value
	/// </summary>
	/// <typeparam name="TSource">Source Type</typeparam>
	/// <typeparam name="TValue">Value Type</typeparam>
	public class OverridableOption<TSource,TValue> where TValue : class
	{

		protected Dictionary<TSource, TValue> Values = new Dictionary<TSource, TValue>();
		/// <summary>
		/// Init with default source and default value
		/// </summary>
		/// <param name="defaultSource">key for default value</param>
		/// <param name="defaultValue">default value</param>
		protected OverridableOption(TSource defaultSource,TValue defaultValue)
		{
			if (defaultValue == null) throw new ArgumentNullException("defaultValue");
			Values[defaultSource] = defaultValue;
		}

		/// <summary>
		/// Init with default source and default value specifying priority strategy
		/// </summary>
		/// <param name="defaultSource">key for default value</param>
		/// <param name="defaultValue">default value</param>
		/// <param name="strategy">Priority sorting strategy</param>
		public OverridableOption(TSource defaultSource,TValue defaultValue,Func<IDictionary<TSource,TValue>,TValue> strategy)
		{
			if (strategy == null) throw new ArgumentNullException("strategy");
			if (defaultValue == null) throw new ArgumentNullException("defaultValue");
			Values[defaultSource] = defaultValue;
			Strategy = strategy;
		}

		/// <summary>
		/// Adds value from a source
		/// </summary>
		/// <param name="src">Source id</param>
		/// <param name="value">Option Value</param>
		public void FromSource(TSource src, TValue value)
		{
			if (!IsValid(value)) return;
			Values[src] = value;
			_value = null;
		}

		/// <summary>
		/// Checks if a value is valid.
		/// Default checks if it's null
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		protected virtual bool IsValid(TValue value)
		{
			return value != null;
		}

		///<summary>
		/// Priority sorting strategy
		///</summary>
		protected Func<IDictionary<TSource, TValue>, TValue> Strategy;

		private TValue _value;

		/// <summary>
		/// Gets option's final value
		/// </summary>
		public TValue Value
		{
			get
			{
				if (_value == null) _value = Strategy(Values);
				return _value;
			}
		}

	}
}