text:
#region copyright

#endregion

namespace YAF.Core.Services
{
    #region

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Web;

    using VZF.Data.Common;
    using VZF.Data.DAL;

    using YAF.Classes;

    using YAF.Types;
    using YAF.Types.Constants;
    using YAF.Types.Flags;
    using YAF.Types.Interfaces;
    using YAF.Types.Objects;
    using VZF.Utils;
    using VZF.Utils.Helpers;

    #endregion

    /// <summary>
    /// Class used for multi-step DB operations so they can be cached, etc.
    /// </summary>
    public class YafDBBroker : IDBBroker, IHaveServiceLocator
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="YafDBBroker"/> class.
        /// </summary>
        /// <param name="serviceLocator">
        /// The service locator.
        /// </param>
        /// <param name="httpSessionState">
        /// The http session state.
        /// </param>
        /// <param name="dataCache">
        /// The data cache.
        /// </param>
        public YafDBBroker(IServiceLocator serviceLocator, HttpSessionStateBase httpSessionState, IDataCache dataCache)
        {
            this.ServiceLocator = serviceLocator;
            this.HttpSessionState = httpSessionState;
            this.DataCache = dataCache;
        }

        #endregion

        #region Properties

        /// <summary>
        ///   Gets or sets DataCache.
        /// </summary>
        public IDataCache DataCache { get; set; }

        /// <summary>
        ///   Gets or sets HttpSessionState.
        /// </summary>
        public HttpSessionStateBase HttpSessionState { get; set; }

        /// <summary>
        ///   Gets or sets ServiceLocator.
        /// </summary>
        public IServiceLocator ServiceLocator { get; set; }

        #endregion

        #region Implemented Interfaces

        #region IDBBroker

        /// <summary>
        /// The user lazy data.
        /// </summary>
        /// <param name="userId">
        /// The user ID.
        /// </param>
        /// <returns>
        /// Returns the Active User
        /// </returns>
        public DataRow ActiveUserLazyData(int userId)
        {
            // get a row with user lazy data...
            return
                this.DataCache.GetOrSet(
                    Constants.Cache.ActiveUserLazyData.FormatWith(userId),
                    () =>
                    CommonDb.user_lazydata(
                        YafContext.Current.PageModuleID,
                        userId,
                        YafContext.Current.PageBoardID,
                        this.Get<YafBoardSettings>().AllowEmailSending,
                        this.Get<YafBoardSettings>().EnableBuddyList,
                        this.Get<YafBoardSettings>().AllowPrivateMessages,
                        this.Get<YafBoardSettings>().EnableAlbum,
                        this.Get<YafBoardSettings>().UseStyledNicks).Table,
                    TimeSpan.FromMinutes(this.Get<YafBoardSettings>().ActiveUserLazyDataCacheTimeout)).Rows[0];
        }

        /// <summary>
        /// Adds the Thanks info to a dataTable
        /// </summary>
        /// <param name="dataRows">
        /// The data Rows.
        /// </param>
        public void AddThanksInfo(IEnumerable<DataRow> dataRows)
        {
            var postRows = dataRows as List<DataRow> ?? dataRows.ToList();
            var messageIds = postRows.Select(x => x.Field<int>("MessageID"));

            // Initialize the "IsthankedByUser" column.
            postRows.ForEach(x => x["IsThankedByUser"] = false);

            // Initialize the "Thank Info" column.
            postRows.ForEach(x => x["ThanksInfo"] = string.Empty);

            // Iterate through all the thanks relating to this topic and make appropriate
            // changes in columns.
            var allThanks = CommonDb.MessageGetAllThanks(YafContext.Current.PageModuleID, messageIds.ToDelimitedString(","));

            var typedAllThankses = allThanks as List<TypedAllThanks> ?? allThanks.ToList();
            foreach (var f in
                typedAllThankses.Where(t => t.FromUserID != null && t.FromUserID == YafContext.Current.PageUserID).SelectMany(
                    thanks => postRows.Where(x => x.Field<int>("MessageID") == thanks.MessageID)))
            {
                f["IsThankedByUser"] = "true";
                f.AcceptChanges();
            }

            var thanksFieldNames = new[] { "ThanksFromUserNumber", "ThanksToUserNumber", "ThanksToUserPostsNumber" };

            foreach (DataRow postRow in postRows)
            {
                var messageId = postRow.Field<int>("MessageID");

                postRow["MessageThanksNumber"] =
                    typedAllThankses.Count(t => t.FromUserID != null && t.MessageID == messageId);

                var thanksFiltered = typedAllThankses.Where(t => t.MessageID == messageId);

                var allThankses = thanksFiltered as List<TypedAllThanks> ?? thanksFiltered.ToList();
                if (allThankses.Any())
                {
                    var thanksItem = allThankses.First();

                    postRow["ThanksFromUserNumber"] = thanksItem.ThanksFromUserNumber ?? 0;
                    postRow["ThanksToUserNumber"] = thanksItem.ThanksToUserNumber ?? 0;
                    postRow["ThanksToUserPostsNumber"] = thanksItem.ThanksToUserPostsNumber ?? 0;
                }
                else
                {
                    DataRow row = postRow;
                    thanksFieldNames.ForEach(f => row[f] = 0);
                }

                // load all all thanks info into a special column...
                postRow["ThanksInfo"] =
                    allThankses.Where(t => t.FromUserID != null).Select(
                        x => "{0}|{1}".FormatWith(x.FromUserID.Value, x.ThanksDate)).ToDelimitedString(",");

                postRow.AcceptChanges();
            }
        }

        /// <summary>
        /// Returns the layout of the board
        /// </summary>
        /// <param name="boardID">
        /// The board ID.
        /// </param>
        /// <param name="userID">
        /// The user ID.
        /// </param>
        /// <param name="categoryID">
        /// The category ID.
        /// </param>
        /// <param name="parentID">
        /// The parent ID.
        /// </param>
        /// <returns>
        /// The board layout.
        /// </returns>
        public DataSet BoardLayout(int boardID, int userID, int? categoryID, int? parentID)
        {
            if (categoryID.HasValue && categoryID == 0)
            {
                categoryID = null;
            }

            using (var ds = new DataSet())
            {
                DataTable moderator;
                if (this.Get<YafBoardSettings>().ShowModeratorList)
                {
                    moderator = this.GetModerators();
                }
                else
                {
                    // add dummy table.
                    moderator = new DataTable(SqlDbAccess.GetVzfObjectName("Moderator", YafContext.Current.PageModuleID));
                    moderator.Columns.AddRange(
                        new[]
                            {
                                new DataColumn("ForumID", typeof(int)),
                                new DataColumn("ForumName", typeof(string)),
                                new DataColumn("ModeratorName", typeof(string)),
                                new DataColumn("ModeratorDisplayName", typeof(string)),
                                new DataColumn("ModeratorEmail", typeof(string)),
                                new DataColumn("ModeratorAvatar", typeof(string)),
                                new DataColumn("ModeratorAvatarImage", typeof(bool)),
                                new DataColumn("Style", typeof(string)),
                                new DataColumn("IsGroup", typeof(bool))
                            });
                   // moderator.Constraints.Add("PK_Mod_ForumID", moderator.Columns["ForumID"], true);
                }

                // insert it into this DataSet
                ds.Tables.Add(moderator.Copy());

                // get the Category Table
                DataTable category = this.DataCache.GetOrSet(
                    Constants.Cache.ForumCategory,
                    () =>
                        {
                            var catDt = CommonDb.category_list(YafContext.Current.PageModuleID, boardID, null);
                            catDt.TableName = SqlDbAccess.GetVzfObjectName("Category", YafContext.Current.PageModuleID);
                            return catDt;
                        },
                    TimeSpan.FromMinutes(this.Get<YafBoardSettings>().BoardCategoriesCacheTimeout));

                // add it to this dataset
                ds.Tables.Add(category.Copy());

                DataTable categoryTable = ds.Tables[SqlDbAccess.GetVzfObjectName("Category", YafContext.Current.PageModuleID)];

                if (categoryID.HasValue)
                {
                    // make sure this only has the category desired in the dataset
                    foreach (DataRow row in
                        categoryTable.AsEnumerable().Where(row => row.Field<int>("CategoryID") != categoryID))
                    {
                        // delete it...
                        row.Delete();
                    }

                    categoryTable.AcceptChanges();
                }

                DataTable forum = CommonDb.forum_listread(
                    YafContext.Current.PageModuleID,
                    boardID,
                    userID,
                    categoryID,
                    parentID,
                    this.Get<YafBoardSettings>().UseStyledNicks,
                    this.Get<YafBoardSettings>().UseReadTrackingByDatabase,
                    true,
                    false,
                    null);
                forum.TableName = SqlDbAccess.GetVzfObjectName("Forum", YafContext.Current.PageModuleID);
                ds.Tables.Add(forum.Copy());

                ds.Relations.Add(
                    "FK_Forum_Category",
                    categoryTable.Columns["CategoryID"],
                    ds.Tables[SqlDbAccess.GetVzfObjectName("Forum", YafContext.Current.PageModuleID)].Columns["CategoryID"],
                    false);
                ds.Relations.Add(
                    "FK_Moderator_Forum",
                    ds.Tables[SqlDbAccess.GetVzfObjectName("Forum", YafContext.Current.PageModuleID)].Columns["ForumID"],
                    ds.Tables[SqlDbAccess.GetVzfObjectName("Moderator", YafContext.Current.PageModuleID)].Columns["ForumID"],
                    false);

                bool deletedCategory = false;

                // remove empty categories...
                foreach (DataRow row in
                    categoryTable.SelectTypedList(row => new { row, childRows = row.GetChildRows("FK_Forum_Category") })
                                 .Where(@t => !@t.childRows.Any())
                                 .Select(@t => @t.row))
                {
                    // remove this category...
                    row.Delete();
                    deletedCategory = true;
                }

                if (deletedCategory)
                {
                    categoryTable.AcceptChanges();
                }

                return ds;
            }
        }

        /// <summary>
        /// The favorite topic list.
        /// </summary>
        /// <param name="userID">
        /// The user ID.
        /// </param>
        /// <returns>
        /// Returns The favorite topic list.
        /// </returns>
        public List<int> FavoriteTopicList(int userID)
        {
            string key = this.Get<ITreatCacheKey>().Treat(Constants.Cache.FavoriteTopicList.FormatWith(userID));

            // stored in the user session...
            var favoriteTopicList = this.HttpSessionState[key] as List<int>;

            // was it in the cache?
            if (favoriteTopicList == null)
            {
                // get fresh values
                DataTable favoriteTopicListDt = CommonDb.topic_favorite_list(YafContext.Current.PageModuleID, userID);

                // convert to list...
                favoriteTopicList = favoriteTopicListDt.GetColumnAsList<int>("TopicID");

                // store it in the user session...
                this.HttpSessionState.Add(key, favoriteTopicList);
            }

            return favoriteTopicList;
        }

        /// <summary>
        /// The get active list.
        /// </summary>
        /// <param name="guests">
        /// The guests.
        /// </param>
        /// <param name="crawlers">
        /// The bots.
        /// </param>
        /// <returns>
        /// Returns the active list.
        /// </returns>
        public DataTable GetActiveList(bool guests, bool crawlers)
        {
            return this.GetActiveList(this.Get<YafBoardSettings>().ActiveListTime, guests, crawlers);
        }

        /// <summary>
        /// The get active list.
        /// </summary>
        /// <param name="activeTime">
        /// The active time.
        /// </param>
        /// <param name="guests">
        /// The guests.
        /// </param>
        /// <param name="crawlers">
        /// The crawlers.
        /// </param>
        /// <returns>
        /// Returns the active list.
        /// </returns>
        public DataTable GetActiveList(int activeTime, bool guests, bool crawlers)
        {
            return
                this.StyleTransformDataTable(
                    CommonDb.active_list(
                        YafContext.Current.PageModuleID,
                        YafContext.Current.PageBoardID,
                        guests,
                        crawlers,
                        activeTime,
                        this.Get<YafBoardSettings>().UseStyledNicks));
        }

        /// <summary>
        /// The get all moderators.
        /// </summary>
        /// <returns>
        /// Returns List with all moderators
        /// </returns>
        public List<SimpleModerator> GetAllModerators()
        {
            // get the cached version of forum moderators if it's valid
            var moderator = this.GetModerators();

            if (this.Get<YafBoardSettings>().UseStyledNicks)
            {
                this.Get<IStyleTransform>().DecodeStyleByTable(ref moderator, false);
            }

            return
                moderator.SelectTypedList(
                    row =>
                    new SimpleModerator(
                        row.Field<int>("ForumID"),
                        row.Field<string>("ForumName"),
                        row.Field<int>("ModeratorID"),
                        row.Field<string>("ModeratorName"),
                        row.Field<string>("ModeratorEmail"),
                        row.Field<string>("ModeratorAvatar"),
                        row.Field<bool>("ModeratorAvatarImage"),
                        row.Field<string>("ModeratorDisplayName"),
                        row.Field<string>("Style"),
                        row["IsGroup"].ToType<bool>())).ToList();
        }

        /// <summary>
        /// The get custom bb code.
        /// </summary>
        /// <returns>
        /// Returns List with Custom BBCodes
        /// </returns>
        public IEnumerable<TypedBBCode> GetCustomBBCode()
        {
            return this.DataCache.GetOrSet(
                Constants.Cache.CustomBBCode, () => CommonDb.BBCodeList(YafContext.Current.PageModuleID, YafContext.Current.PageBoardID, null).ToList());
        }

        /// <summary>
        /// The get latest topics.
        /// </summary>
        /// <param name="numberOfPosts">
        /// The number of posts.
        /// </param>
        /// <returns>
        /// Returns List with Latest Topics.
        /// </returns>
        public DataTable GetLatestTopics(int numberOfPosts)
        {
            return this.GetLatestTopics(numberOfPosts, YafContext.Current.PageUserID);
        }

        /// <summary>
        /// The get latest topics.
        /// </summary>
        /// <param name="numberOfPosts">
        /// The number of posts.
        /// </param>
        /// <param name="userId">
        /// The user id.
        /// </param>
        /// <param name="styleColumnNames">
        /// The style Column Names.
        /// </param>
        /// <returns>
        /// Returns List with Latest Topics.
        /// </returns>
        public DataTable GetLatestTopics(int numberOfPosts, int userId, params string[] styleColumnNames)
        {
            return
                this.StyleTransformDataTable(
                    CommonDb.topic_latest(
                        YafContext.Current.PageModuleID,
                        YafContext.Current.PageBoardID,
                        numberOfPosts,
                        userId,
                        this.Get<YafBoardSettings>().UseStyledNicks,
                        this.Get<YafBoardSettings>().NoCountForumsInActiveDiscussions,
                        this.Get<YafBoardSettings>().UseReadTrackingByDatabase),
                    styleColumnNames);
        }

        /// <summary>
        /// Get all moderators by Groups and User
        /// </summary>
        /// <returns>
        /// Returns the Moderator List
        /// </returns>
        public DataTable GetModerators()
        {
            return this.DataCache.GetOrSet(
                Constants.Cache.ForumModerators,
                () =>
                    {
                        DataTable moderator = CommonDb.forum_moderators(
                            YafContext.Current.PageModuleID, this.Get<YafBoardSettings>().UseStyledNicks);
                        moderator.TableName = SqlDbAccess.GetVzfObjectName("Moderator", YafContext.Current.PageModuleID);
                        return moderator;
                    },
                TimeSpan.FromMinutes(this.Get<YafBoardSettings>().BoardModeratorsCacheTimeout));
        }

        /// <summary>
        /// Get the list of recently logged in users.
        /// </summary>
        /// <param name="timeSinceLastLogin">
        /// The time since last login in minutes.
        /// </param>
        /// <returns>
        /// The list of users in DataTable format.
        /// </returns>
        public DataTable GetRecentUsers(int timeSinceLastLogin)
        {
            return
                this.StyleTransformDataTable(
                    CommonDb.recent_users(YafContext.Current.PageModuleID, YafContext.Current.PageBoardID, timeSinceLastLogin, this.Get<YafBoardSettings>().UseStyledNicks));
        }

        /// <summary>
        /// The get shout box messages.
        /// </summary>
        /// <param name="boardId">
        /// The board id.
        /// </param>
        /// <returns>
        /// Returns the shout box messages.
        /// </returns>
        public IEnumerable<DataRow> GetShoutBoxMessages(int boardId)
        {
            return this.DataCache.GetOrSet(
                Constants.Cache.Shoutbox,
                () =>
                    {
                        var messages = CommonDb.shoutbox_getmessages(
                            YafContext.Current.PageModuleID,
                            boardId,
                            this.Get<YafBoardSettings>().ShoutboxShowMessageCount,
                            this.Get<YafBoardSettings>().UseStyledNicks);

                        // Set colorOnly parameter to false, as we get all color info from data base
                        if (this.Get<YafBoardSettings>().UseStyledNicks)
                        {
                            this.Get<IStyleTransform>().DecodeStyleByTable(ref messages, false);
                        }

                        var flags = new MessageFlags { IsBBCode = true, IsHtml = false };

                        foreach (var row in messages.AsEnumerable())
                        {
                            string formattedMessage =
                                this.Get<IFormatMessage>().FormatMessage(row.Field<string>("Message"), flags);

                            // Extra Formating not needed already done tru this.Get<IFormatMessage>().FormatMessage
                            // formattedMessage = FormatHyperLink(formattedMessage);
                            row["Message"] = formattedMessage;
                        }

                        return messages;
                    },
                TimeSpan.FromMilliseconds(30000)).AsEnumerable();
        }

        /// <summary>
        /// Get a simple forum/topic listing.
        /// </summary>
        /// <param name="boardId">
        /// The board Id.
        /// </param>
        /// <param name="userId">
        /// The user Id.
        /// </param>
        /// <param name="timeFrame">
        /// The time Frame.
        /// </param>
        /// <param name="maxCount">
        /// The max Count.
        /// </param>
        /// <returns>
        /// The get simple forum topic.
        /// </returns>
        public List<SimpleForum> GetSimpleForumTopic(int boardId, int userId, DateTime timeFrame, int maxCount)
        {
            var forumData =
                CommonDb.forum_listall(YafContext.Current.PageModuleID, boardId, userId).SelectTypedList(
                    x => new SimpleForum { ForumID = x.Field<int>("ForumID"), Name = x.Field<string>("Forum") }).ToList();

            // get topics for all forums...
            foreach (var forum in forumData)
            {
                SimpleForum forum1 = forum;

                // add topics
                var topics =
                    CommonDb.topic_list(
                        YafContext.Current.PageModuleID,
                        forum.ForumID,
                        userId,
                        timeFrame,
                        DateTime.UtcNow,
                        0,
                        maxCount,
                        false,
                        false, false,
                        false,
                        this.Get<YafBoardSettings>().AllowTopicTags).AsEnumerable();

                // filter first...
                forum.Topics = topics.Where(x => x.Field<DateTime>("LastPosted") >= timeFrame)
                                      .Select(x => this.LoadSimpleTopic(x, forum1))
                                        .ToList();
            }

            return forumData;
        }

        /// <summary>
        /// The get smilies.
        /// </summary>
        /// <returns>
        /// Table with list of smilies
        /// </returns>
        public IEnumerable<TypedSmileyList> GetSmilies()
        {
            return this.DataCache.GetOrSet(
                Constants.Cache.Smilies,
                () => CommonDb.SmileyList(YafContext.Current.PageModuleID, YafContext.Current.PageBoardID, null).ToList(),
                TimeSpan.FromMinutes(60));
        }

        /// <summary>
        /// Loads the message text into the paged data if "Message" and "MessageID" exists.
        /// </summary>
        /// <param name="dataRows">
        /// The data Rows.
        /// </param>
        public void LoadMessageText(IEnumerable<DataRow> dataRows)
        {
            var enumerable = dataRows as IList<DataRow> ?? dataRows.ToList();
            var messageIds =
                enumerable.AsEnumerable().Where(x => x.Field<string>("Message").IsNotSet()).Select(
                    x => x.Field<int>("MessageID"));

            var messageTextTable = CommonDb.message_GetTextByIds(YafContext.Current.PageModuleID, messageIds.ToDelimitedString(","));

            if (messageTextTable == null)
            {
                return;
            }

            // load them into the page data...
            foreach (var dataRow in enumerable)
            {
                // find the message id in the results...
                DataRow row = dataRow;

                var message =
                    messageTextTable.AsEnumerable().FirstOrDefault(x => x.Field<int>("MessageID") == row.Field<int>("MessageID"));

                if (message == null)
                {
                    continue;
                }

                dataRow.BeginEdit();
                dataRow["Message"] = message.Field<string>("Message");
                dataRow.EndEdit();
            }
        }

        /// <summary>
        /// The style transform func wrap.
        /// </summary>
        /// <param name="dt">
        /// The DateTable
        /// </param>
        /// <returns>
        /// The style transform wrap.
        /// </returns>
        public DataTable StyleTransformDataTable(DataTable dt)
        {
            if (this.Get<YafBoardSettings>().UseStyledNicks)
            {
                var styleTransform = this.Get<IStyleTransform>();
                styleTransform.DecodeStyleByTable(ref dt, true);
            }

            return dt;
        }

        /// <summary>
        /// The style transform func wrap.
        /// </summary>
        /// <param name="dt">
        /// The DateTable
        /// </param>
        /// <param name="styleColumns">
        /// Style columns names
        /// </param>
        /// <returns>
        /// The style transform wrap.
        /// </returns>
        public DataTable StyleTransformDataTable(DataTable dt, params string[] styleColumns)
        {
            if (this.Get<YafBoardSettings>().UseStyledNicks)
            {
                var styleTransform = this.Get<IStyleTransform>();
                styleTransform.DecodeStyleByTable(ref dt, true, styleColumns);
            }

            return dt;
        }

        /// <summary>
        /// The Buddy list for the user with the specified UserID.
        /// </summary>
        /// <param name="userId">
        /// The User ID.
        /// </param>
        /// <returns>
        /// The user buddy list.
        /// </returns>
        public DataTable UserBuddyList(int userId)
        {
            return this.DataCache.GetOrSet(
                Constants.Cache.UserBuddies.FormatWith(userId),
                () => CommonDb.buddy_list(YafContext.Current.PageModuleID, userId),
                TimeSpan.FromMinutes(10));
        }

        /// <summary>
        /// The user ignored list.
        /// </summary>
        /// <param name="userId">
        /// The user id.
        /// </param>
        /// <returns>
        /// Returns the user ignored list.
        /// </returns>
        public List<int> UserIgnoredList(int userId)
        {
            string key = Constants.Cache.UserIgnoreList.FormatWith(userId);

            // stored in the user session...
            var userList = this.HttpSessionState[key] as List<int>;

            // was it in the cache?
            if (userList == null)
            {
                // get fresh values
                DataTable userListDt = CommonDb.user_ignoredlist(YafContext.Current.PageModuleID, userId);

                // convert to list...
                userList = userListDt.GetColumnAsList<int>("IgnoredUserID");

                // store it in the user session...
                this.HttpSessionState.Add(key, userList);
            }

            return userList;
        }

        /// <summary>
        /// The user medals.
        /// </summary>
        /// <param name="userId">
        /// The user id.
        /// </param>
        /// <returns>
        /// Returns the User Medals
        /// </returns>
        public DataTable UserMedals(int userId)
        {
            string key = Constants.Cache.UserMedals.FormatWith(userId);

            // get the medals cached...
            DataTable dt = this.DataCache.GetOrSet(
                key, () => CommonDb.user_listmedals(YafContext.Current.PageModuleID, userId), TimeSpan.FromMinutes(10));

            return dt;
        }

        #endregion

        #endregion

        #region Methods

        /// <summary>
        /// The load simple topic.
        /// </summary>
        /// Creates a Simple Topic item.
        /// <param name="row">
        /// The row.
        /// </param>
        /// <param name="forum">
        /// The forum.
        /// </param>
        /// <returns>
        /// Returns the simple topic.
        /// </returns>
        [NotNull]
        private SimpleTopic LoadSimpleTopic([NotNull] DataRow row, [NotNull] SimpleForum forum)
        {
            CodeContracts.ArgumentNotNull(row, "row");
            CodeContracts.ArgumentNotNull(forum, "forum");

            return new SimpleTopic
                {
                    TopicID = row.Field<int>("TopicID"),
                    CreatedDate = row.Field<DateTime>("Posted"),
                    Subject = row.Field<string>("Subject"),
                    StartedUserID = row.Field<int>("UserID"),
                    StartedUserName = UserMembershipHelper.GetDisplayNameFromID(row.Field<int>("UserID")),
                    Replies = row.Field<int>("Replies"),
                    LastPostDate = row.Field<DateTime>("LastPosted"),
                    LastUserID = row.Field<int>("LastUserID"),
                    LastUserName = UserMembershipHelper.GetDisplayNameFromID(row.Field<int>("LastUserID")),
                    LastMessageID = row.Field<int>("LastMessageID"),
                    FirstMessage = row.Field<string>("FirstMessage"),
                    LastMessage = CommonDb.MessageList(YafContext.Current.PageModuleID, row.Field<int>("LastMessageID")).First().Message,
                    Forum = forum
                };
        }

        #endregion
    }
}


text:
namespace theia {

class Reconstruction;

// Writes the reconstruction to a binary file. Only the estimated views and
// tracks are output.
//
// See //theia/sfm/reconstruction.h for more details about the
// information contained in a reconstruction.
bool WriteReconstruction(const Reconstruction& reconstruction,
                         const std::string& output_file);

}  // namespace theia

#endif  // THEIA_IO_RECONSTRUCTION_WRITER_H_

redpajama_set_name: RedPajamaGithub


text:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
					 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
					 xsi:schemaLocation="http://jakarta.apache.org/log4j/ ">

	<!-- Appenders -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out"/>
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d |%t| %-1p [%c] - %m%n"/>
		</layout>
	</appender>

	<appender name="fileAppender" class="org.apache.log4j.DailyRollingFileAppender">
		<param name="file" value="${catalina.base}/logs/sws.log"/>
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d |%t| %-1p [%c] - %m%n"/>
		</layout>
	</appender>

	<!-- Application Loggers -->
	<logger name="org.springframework.samples.webflow">
		<level value="debug"/>
	</logger>

	<!-- 3rdparty Loggers -->
	<logger name="org.springframework.core">
		<level value="info"/>
	</logger>

	<logger name="org.springframework.beans">
		<level value="info"/>
	</logger>

	<logger name="org.springframework.context">
		<level value="info"/>
	</logger>

	<logger name="org.springframework.http">
		<level value="info"/>
	</logger>

	<logger name="org.springframework.web">
		<level value="debug"/>
	</logger>

	<logger name="org.springframework.binding">
		<level value="info"/>
	</logger>

	<logger name="org.springframework.webflow">
		<level value="debug"/>
	</logger>

	<logger name="org.primefaces">
		<level value="debug"/>
	</logger>

	<!-- Root Logger -->
	<root>
		<priority value="info"/>
		<appender-ref ref="console"/>
		<appender-ref ref="fileAppender"/>
	</root>

</log4j:configuration>


text:
@interface PodsDummy_Pods_WatchContacts : NSObject
@end
@implementation PodsDummy_Pods_WatchContacts
@end


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>org.robolectric.internal</title>
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Tree

Deprecated

Index

Help

Robolectric 4.2 |

Prev Package

Next Package

Frames

No Frames

All Classes

Package org.robolectric.internal

Interface Summary

Interface
Description

Environment

IShadow

ManifestFactory

A factory that detects what build system is in use and provides a ManifestFactory that can create an AndroidManifest for that environment.

SandboxManager.SandboxBuilder

Factory interface for AndroidSandbox.

ShadowProvider

Interface implemented by packages that provide shadows to Robolectric.

Class Summary

Class
Description

AndroidConfigurer

AndroidSandbox

Sandbox simulating an Android device.

AndroidSandbox.EnvironmentSpec

Provides a mechanism for tests to inject a different AndroidEnvironment.

AndroidSandbox.SdkSandboxClassLoader

Adapter from Sdk to ResourceLoader.

BuckManifestFactory

DefaultManifestFactory

ManifestIdentifier

MavenManifestFactory
Deprecated

This method of configuration will be removed in a forthcoming release.

SandboxManager

Manager of sandboxes.

SandboxTestRunner

SandboxTestRunner.HelperTestRunner

Enum Summary

Enum
Description

ResourcesMode

Exception Summary

Exception
Description

DeprecatedMethodMarkerException

Skip navigation links

Overview

Package

Class

Tree

Deprecated

Index

Help

Robolectric 4.2 |

Prev Package

Next Package

Frames

No Frames

All Classes


text:
#if !defined(MITK_PLANEFIT_H__INCLUDED_)
#define MITK_PLANEFIT_H__INCLUDED_

#include "mitkPointSet.h"
#include "MitkAlgorithmsExtExports.h"
#include "mitkTimeGeometry.h"
#include "mitkPlaneGeometry.h"
#include "mitkGeometryDataSource.h"

namespace mitk {

  //!
  //  kind regards to dr. math!
  // function [x0, a, d, normd] = lsplane(X)
  // ---------------------------------------------------------------------
  // LSPLANE.M   Least-squares plane (orthogonal distance
  //             regression).
  //
  // Version 1.0
  // Last amended   I M Smith 27 May 2002.
  // Created        I M Smith 08 Mar 2002
  // ---------------------------------------------------------------------
  // Input
  // X        Array [x y z] where x = vector of x-coordinates,
  //          y = vector of y-coordinates and z = vector of
  //          z-coordinates.
  //          Dimension: m x 3.
  //
  // Output
  // x0       Centroid of the data = point on the best-fit plane.
  //          Dimension: 3 x 1.
  //
  // a        Direction cosines of the normal to the best-fit
  //          plane.
  //          Dimension: 3 x 1.
  //
  // <Optional...
  // d        Residuals.
  //          Dimension: m x 1.
  //
  // normd    Norm of residual errors.
  //          Dimension: 1 x 1.
  // ...>
  //
  // [x0, a <, d, normd >] = lsplane(X)
  // ---------------------------------------------------------------------

  class MITKALGORITHMSEXT_EXPORT PlaneFit : public GeometryDataSource
  {
    public:

      mitkClassMacro( PlaneFit, GeometryDataSource);
      itkNewMacro(Self);

      typedef mitk::PointSet::PointDataType PointDataType;
      typedef mitk::PointSet::PointDataIterator PointDataIterator;

      virtual void GenerateOutputInformation() override;

      virtual void GenerateData() override;

      /*!Getter for point set.
       *
       */
      const mitk::PointSet *GetInput();

      /*! filter initialisation.
       *
       */
      using mitk::GeometryDataSource::SetInput;
      virtual void SetInput( const mitk::PointSet *ps );

      /*! returns the center of gravity of the point set.
       *
       */
      virtual const mitk::Point3D &GetCentroid( int t = 0 ) const;

      /*! returns the plane geometry which represents the point set.
       *
       */
      virtual mitk::PlaneGeometry::Pointer GetPlaneGeometry( int t = 0 );

      /*! returns the normal of the plane which represents the point set.
       *
       */
      virtual const mitk::Vector3D &GetPlaneNormal( int t = 0 ) const;

    protected:
      PlaneFit();
      virtual ~PlaneFit();

      /*! Calculates the centroid of the point set.
       * the center of gravity is calculated  through the mean value of the whole point set
       */
      void CalculateCentroid( int t = 0 );

      /*! working with an SVD algorithm form matrix dataM.
       * ITK suplies the vnl_svd to solve an plan fit eigentvector problem
       * points are processed in the SVD matrix. The normal vector is the
       * singular vector of dataM corresponding to its smalest singular value.
       * The mehtod uses VNL library from ITK and at least the mehtod nullvector()
       * to extract the normalvector.
       */
      void ProcessPointSet( int t = 0 );

      /*! Initialize Plane and configuration.
       *
       */
      void InitializePlane( int t = 0 );

    private:

      /*!keeps a copy of the pointset.*/
      const mitk::PointSet* m_PointSet;

      /* output object - a time sliced geometry.*/
      mitk::TimeGeometry::Pointer m_TimeGeometry;

      std::vector< mitk::PlaneGeometry::Pointer > m_Planes;

      /*! the calculatet center point of all points in the point set.*/
      std::vector< mitk::Point3D > m_Centroids;

      /* the normal vector to descrie a plane gemoetry.*/
      std::vector< mitk::Vector3D > m_PlaneVectors;
  };
}//namespace mitk
#endif //MITK_PLANFIT_INCLUDE_


text:
Konsento is an open source software licensed under the [MIT License](http://choosealicense.com/licenses/mit/), meaning anyone can freely see, use, contribute to, change and redistribute the source code, as long as the copyrights to the ONG and the license are kept, and the ONG is not held liable.

## How to contribute to the source code
If you want to contribute to Konsento's source code, here are a few tips and guidelines.

### Find where to help
The first thing you should do is to find where to help.

#### GitHub issues
The easiest way to find where to help is to check for [open issues in the repository](https://github.com/konsento/konsento/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20), or open one yourself if you find any bug.

#### GitHub project
You can check the progress of the issues on the GitHub [project](https://github.com/konsento/konsento/projects/1).

#### Facebook group
If you have any question or suggestion, you can always post it on [our facebook group](https://www.facebook.com/groups/dddcp/) and discuss about it with everyone interested, before committing yourself into making changes to the source code.

### Hack some code!
It's time to hack some code and submit it. [There's a GitHub's comprehensive guide to contributing](https://help.github.com/articles/fork-a-repo/), but here are the basic steps:

#### Register to GitHub
GitHub is the world's largest programming collaboration tool in the world, if you're not registered yet, [register for an account](https://github.com/join), you'll need it.

#### Fork and clone the repo
Fork the repository so you can make the changes, just click the fork button at the top right of the repository page. You'll need a local copy of your fork of the repository, so head over to you fork and clone it.

#### Create a new branch, make changes and test
Create a new local branch in your local clone and make some changes using your favorite code editor or IDE. Remember to change or create the respective tests, they'll need to pass for your changes to be accepted.

#### Commit, push and pull request
Now commit the changes you've made, push to your fork of the repository and create a pull request.
We use [Travis CI](https://travis-ci.org/), so when your pull request is created all tests will be automatically run, if any of them don't pass you'll have to check what's wrong, fix it, commit and push before you changes can be merged.

Feel free to comment on the pull request with questions to any of the repo admins.


text:
Merchants
=========

Merchants have an ordinary bank account like anyone else, except they simply use the ::ref:`terminal<_terminals>`_ functionality to receive payments. In order to make tax considerably simpler and potentially entirely automated, all the required information for tax purposes can be found on the bank statement.

Salaries/ Wages
---------------

Typically salaries are handled as subscriptions. In effect, the company is subscribing to an employee's work. This way the payment is entirely automated and it can safely vary from month to month too. Using device privileges, a HR department can access these specific subscriptions.


text:
package org.jivesoftware.util;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Dispatches property events. Each event has a {@link EventType type}
 * and optional parameters, as follows:

 *
 *

 *
Event Type	Extra Params

 *
{@link EventType#property_set property_set}	A param named <tt>value</tt> that
 *      has the value of the property set.

 *
{@link EventType#property_deleted property_deleted}	None

 *
{@link EventType#xml_property_set xml_property_set}	A param named <tt>value</tt> that
 *      has the value of the property set.

 *
{@link EventType#xml_property_deleted xml_property_deleted}	None

 *

 *
 * @author Matt Tucker
 */
public class PropertyEventDispatcher {

    private static Set<PropertyEventListener> listeners =
            new CopyOnWriteArraySet<PropertyEventListener>();

    private PropertyEventDispatcher() {
        // Not instantiable.
    }

    /**
     * Registers a listener to receive events.
     *
     * @param listener the listener.
     */
    public static void addListener(PropertyEventListener listener) {
        if (listener == null) {
            throw new NullPointerException();
        }
        listeners.add(listener);
    }

    /**
     * Unregisters a listener to receive events.
     *
     * @param listener the listener.
     */
    public static void removeListener(PropertyEventListener listener) {
        listeners.remove(listener);
    }

    /**
     * Dispatches an event to all listeners.
     *
     * @param property the property.
     * @param eventType the event type.
     * @param params event parameters.
     */
    public static void dispatchEvent(String property, EventType eventType, Map<String, Object> params) {
        for (PropertyEventListener listener : listeners) {
            try {
                switch (eventType) {
                    case property_set: {
                        listener.propertySet(property, params);
                        break;
                    }
                    case property_deleted: {
                        listener.propertyDeleted(property, params);
                        break;
                    }
                    case xml_property_set: {
                        listener.xmlPropertySet(property, params);
                        break;
                    }
                    case xml_property_deleted: {
                        listener.xmlPropertyDeleted(property, params);
                        break;
                    }
                    default:
                        break;
                }
            }
            catch (Exception e) {
                // Log.error(e);
                e.printStackTrace();
            }
        }
    }

    /**
     * Represents valid event types.
     */
    public enum EventType {

        /**
         * A property was set.
         */
        property_set,

        /**
         * A property was deleted.
         */
        property_deleted,

        /**
         * An XML property was set.
         */
        xml_property_set,

        /**
         * An XML property was deleted.
         */
        xml_property_deleted;
    }
}


text:
using Microsoft.Owin;
using Owin;

[assembly: OwinStartupAttribute(typeof(Pai.Startup))]
namespace Pai
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}


text: hdasjdasdjasj


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
Hedwigia 34: 115 (1895)

#### Original name
Gloeosporium papayae Henn.

### Remarks
null


text:
package libmemcached.wrapper.function;

import static libmemcached.wrapper.function.Memcached.memcached_create;
import static libmemcached.wrapper.function.Memcached.memcached_free;
import static libmemcached.wrapper.function.Stats.memcached_stat;
import static libmemcached.wrapper.function.Stats.memcached_stat_free;

import libmemcached.exception.LibMemcachedException;
import libmemcached.memcached.memcached_st;
import libmemcached.stats.memcached_stat_st;

import org.junit.Assert;
import org.junit.Test;

public class StatsTest {

    @Test
    public void testMemcached_statMemcached() throws LibMemcachedException {
        /*
        memcached_st memc = memcached_create();
        memcached_stat_st stat = memcached_stat(memc);
        Assert.assertNotNull(stat);
        memcached_stat_free(memc, stat);
        memcached_free(memc);
        */
    }

    @Test
    public void testMemcached_statMemcached_stString() throws LibMemcachedException {
        /*
        memcached_st memc = memcached_create();
        {
            memcached_stat_st stat = memcached_stat(memc, null);
            Assert.assertNotNull(stat);
            memcached_stat_free(memc, stat);
        }
        {
            memcached_stat_st stat = memcached_stat(memc, "123456789");
            Assert.assertNotNull(stat);
            memcached_stat_free(memc, stat);
        }
        memcached_free(memc);
        */
    }

    @Test
    public void testMemcached_statMemcached_stStringStringInt() throws LibMemcachedException {
        memcached_st memc = memcached_create();
        {
            memcached_stat_st stat = memcached_stat(memc, null, "localhost", 11211);
            Assert.assertNotNull(stat);
            memcached_stat_free(memc, stat);
        }
        /*
        {
            memcached_stat_st stat = memcached_stat(memc, "", "localhost", 11211); // fail args == ""
            Assert.assertNotNull(stat);
            memcached_stat_free(memc, stat);
        }
        */
        memcached_free(memc);
    }

}


text:
package com.twitter.algebird
package benchmark

import scala.util.Random

import org.openjdk.jmh.annotations._
import org.openjdk.jmh.infra.Blackhole

import scala.math._

class OldMonoid(bits: Int) extends HyperLogLogMonoid(bits) {

  override def sumOption(items: TraversableOnce[HLL]): Option[HLL] =
    if (items.isEmpty) None
    else {
      val buffer = new Array[Byte](size)
      items.foreach(_.updateInto(buffer))
      Some(DenseHLL(bits, Bytes(buffer)))
    }
}

object HllBenchmark {

  @State(Scope.Benchmark)
  class HLLState {
    var hllMonoid: HyperLogLogMonoid = _
    var oldHllMonoid: HyperLogLogMonoid = _

    @Param(Array("12", "14", "24"))
    var numBits: Int = 0

    // Old sum option will not work with >=100 keys, and >= 1000 elements.
    @Param(Array("1", "10"))
    var numInputKeys: Int = 0

    @Param(Array("10", "1000", "10000"))
    var numElements: Int = 0

    var inputData: Seq[Seq[HLL]] = _

    @Setup(Level.Trial)
    def setup(): Unit = {
      hllMonoid = new HyperLogLogMonoid(numBits)

      oldHllMonoid = new OldMonoid(numBits)

      val rng = new Random(3)

      def setSize = rng.nextInt(10) + 1 // 1 -> 10
      def hll(elements: Set[Long]): HLL =
        hllMonoid.sum(elements.map(hllMonoid.toHLL[Long](_)))

      val inputIntermediate = (0L until numElements).map { _ =>
        val setElements = (0 until setSize).map(_ => rng.nextInt(1000).toLong).toSet
        (pow(numInputKeys, rng.nextFloat).toLong, List(hll(setElements)))
      }
      inputData = MapAlgebra.sumByKey(inputIntermediate).map(_._2).toSeq
    }
  }
}

class HllBenchmark {
  import HllBenchmark._
  @Benchmark
  def timeSumOption(state: HLLState, bh: Blackhole): Unit =
    state.inputData.foreach(vals => bh.consume(state.hllMonoid.sumOption(vals)))
  @Benchmark
  def timeOldSumOption(state: HLLState, bh: Blackhole): Unit =
    state.inputData.foreach(d => bh.consume(state.oldHllMonoid.sumOption(d)))

  @Benchmark
  def timePlus(state: HLLState, bh: Blackhole): Unit =
    state.inputData.foreach(vals => bh.consume(vals.reduce(state.hllMonoid.plus(_, _))))
}


text:
package org.apache.skywalking.apm.commons.datacarrier.consumer;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.skywalking.apm.commons.datacarrier.DataCarrier;
import org.apache.skywalking.apm.commons.datacarrier.SampleData;
import org.junit.Assert;
import org.junit.Test;
import org.powermock.api.support.membermodification.MemberModifier;

public class ConsumerTest {
    public static LinkedBlockingQueue<SampleData> BUFFER = new LinkedBlockingQueue<SampleData>();

    public static boolean IS_OCCUR_ERROR = false;

    @Test
    public void testConsumerLessThanChannel() throws IllegalAccessException {
        final DataCarrier<SampleData> carrier = new DataCarrier<SampleData>(2, 100);

        for (int i = 0; i < 100; i++) {
            Assert.assertTrue(carrier.produce(new SampleData().setName("data" + i)));
        }
        SampleConsumer consumer = new SampleConsumer();

        consumer.i = 100;
        carrier.consume(SampleConsumer.class, 1);
        Assert.assertEquals(1, ((SampleConsumer) getConsumer(carrier)).i);

        SampleConsumer2 consumer2 = new SampleConsumer2();
        consumer2.i = 100;
        carrier.consume(consumer2, 1);
        Assert.assertEquals(100, ((SampleConsumer2) getConsumer(carrier)).i);

        carrier.shutdownConsumers();
    }

    @Test
    public void testConsumerMoreThanChannel() throws IllegalAccessException, InterruptedException {
        final DataCarrier<SampleData> carrier = new DataCarrier<SampleData>(2, 100);

        for (int i = 0; i < 200; i++) {
            Assert.assertTrue(carrier.produce(new SampleData().setName("data" + i)));
        }
        SampleConsumer consumer = new SampleConsumer();

        carrier.consume(SampleConsumer.class, 5);

        Thread.sleep(2000);

        List<SampleData> result = new ArrayList<SampleData>();
        BUFFER.drainTo(result);

        Assert.assertEquals(200, result.size());

        HashSet<Integer> consumerCounter = new HashSet<Integer>();
        for (SampleData data : result) {
            consumerCounter.add(data.getIntValue());
        }
        Assert.assertEquals(2, consumerCounter.size());
    }

    @Test
    public void testConsumerOnError() throws InterruptedException {
        final DataCarrier<SampleData> carrier = new DataCarrier<SampleData>(2, 100);

        for (int i = 0; i < 200; i++) {
            Assert.assertTrue(carrier.produce(new SampleData().setName("data" + i)));
        }
        SampleConsumer2 consumer = new SampleConsumer2();

        consumer.onError = true;
        carrier.consume(consumer, 5);

        Thread.sleep(3 * 1000L);

        Assert.assertTrue(IS_OCCUR_ERROR);
    }

    class SampleConsumer2 implements IConsumer<SampleData> {
        public int i = 1;

        public boolean onError = false;

        @Override
        public void init() {

        }

        @Override
        public void consume(List<SampleData> data) {
            if (onError) {
                throw new RuntimeException("consume exception");
            }
        }

        @Override
        public void onError(List<SampleData> data, Throwable t) {
            IS_OCCUR_ERROR = true;
        }

        @Override
        public void onExit() {

        }
    }

    private IConsumer getConsumer(DataCarrier<SampleData> carrier) throws IllegalAccessException {
        ConsumeDriver pool = (ConsumeDriver) MemberModifier.field(DataCarrier.class, "driver").get(carrier);
        ConsumerThread[] threads = (ConsumerThread[]) MemberModifier.field(ConsumeDriver.class, "consumerThreads")
                                                                    .get(pool);

        return (IConsumer) MemberModifier.field(ConsumerThread.class, "consumer").get(threads[0]);
    }
}


text:
{% load staticfiles %}
<!DOCTYPE html>
<!--
    Transit by TEMPLATED
    templated.co @templatedco
    Released for free under the Creative Commons Attribution 3.0 license (templated.co/license)
-->
<html lang="en">
    {% include "pswebsite/header.html" %}

    <body>
    {% include "pswebsite/nav.html" %}

    {########## Actual Content ##########}
    {% block content %}{% endblock %}

    {% include "pswebsite/footer.html" %}

    {# Include extra javascript here #}
    {% block jsIncludes %}
        {% for jsFile in extraJsFiles %}
            <script src="{% static jsFile %}"></script>
        {% endfor %}
    {% endblock %}

    {# Put any inline JS here #}
    {% block inlineJS %}{% endblock %}
    </body>
</html>


text:
@interface ZLNavigationController : UINavigationController

@end


text:
/*
 * Module for interfacing with Switec instrument steppers (and
 * similar devices). These are the steppers that are used in automotive
 * instrument panels and the like. Run off 5 volts at low current.
 *
 * Code inspired by:
 *
 * SwitecX25 Arduino Library
 *  Guy Carpenter, Clearwater Software - 2012
 *
 *  Licensed under the BSD2 license, see license.txt for details.
 *
 * NodeMcu integration by Philip Gladstone, N1DQ
 */

#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "c_types.h"
#include "task/task.h"
#include "driver/switec.h"

// This is the reference to the callbacks for when the pointer
// stops moving.
static int stopped_callback[SWITEC_CHANNEL_COUNT] = { LUA_NOREF, LUA_NOREF, LUA_NOREF };
static task_handle_t tasknumber;

static void callback_free(lua_State* L, unsigned int id)
{
  luaL_unref(L, LUA_REGISTRYINDEX, stopped_callback[id]);
  stopped_callback[id] = LUA_NOREF;
}

static void callback_set(lua_State* L, unsigned int id, int argNumber)
{
  if (lua_type(L, argNumber) == LUA_TFUNCTION || lua_type(L, argNumber) == LUA_TLIGHTFUNCTION) {
    lua_pushvalue(L, argNumber);  // copy argument (func) to the top of stack
    callback_free(L, id);
    stopped_callback[id] = luaL_ref(L, LUA_REGISTRYINDEX);
  }
}

static void callback_execute(lua_State* L, unsigned int id)
{
  if (stopped_callback[id] != LUA_NOREF) {
    int callback = stopped_callback[id];
    lua_rawgeti(L, LUA_REGISTRYINDEX, callback);
    callback_free(L, id);

    lua_call(L, 0, 0);
  }
}

int platform_switec_exists( unsigned int id )
{
  return (id < SWITEC_CHANNEL_COUNT);
}

// Lua: setup(id, P1, P2, P3, P4, maxSpeed)
static int lswitec_setup( lua_State* L )
{
  unsigned int id;

  id = luaL_checkinteger( L, 1 );
  MOD_CHECK_ID( switec, id );
  int pin[4];

  if (switec_close(id)) {
    return luaL_error( L, "Unable to setup stepper." );
  }

  int i;
  for (i = 0; i < 4; i++) {
    uint32_t gpio = luaL_checkinteger(L, 2 + i);

    luaL_argcheck(L, platform_gpio_exists(gpio), 2 + i, "Invalid pin");

    pin[i] = pin_num[gpio];

    platform_gpio_mode(gpio, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP);
  }

  int deg_per_sec = 0;
  if (lua_gettop(L) >= 6) {
    deg_per_sec = luaL_checkinteger(L, 6);
  }

  if (switec_setup(id, pin, deg_per_sec, tasknumber)) {
    return luaL_error(L, "Unable to setup stepper.");
  }
  return 0;
}

// Lua: close( id )
static int lswitec_close( lua_State* L )
{
  unsigned int id;

  id = luaL_checkinteger( L, 1 );
  MOD_CHECK_ID( switec, id );
  callback_free(L, id);
  if (switec_close( id )) {
    return luaL_error( L, "Unable to close stepper." );
  }
  return 0;
}

// Lua: reset( id )
static int lswitec_reset( lua_State* L )
{
  unsigned int id;
  id = luaL_checkinteger( L, 1 );
  MOD_CHECK_ID( switec, id );
  if (switec_reset( id )) {
    return luaL_error( L, "Unable to reset stepper." );
  }
  return 0;
}

// Lua: moveto( id, pos [, cb] )
static int lswitec_moveto( lua_State* L )
{
  unsigned int id;

  id = luaL_checkinteger( L, 1 );
  MOD_CHECK_ID( switec, id );
  int pos;
  pos = luaL_checkinteger( L, 2 );

  if (lua_gettop(L) >= 3) {
    callback_set(L, id, 3);
  } else {
    callback_free(L, id);
  }

  if (switec_moveto( id, pos )) {
    return luaL_error( L, "Unable to move stepper." );
  }
  return 0;
}

// Lua: getpos( id ) -> position, moving
static int lswitec_getpos( lua_State* L )
{
  unsigned int id;

  id = luaL_checkinteger( L, 1 );
  MOD_CHECK_ID( switec, id );
  int32_t pos;
  int32_t dir;
  int32_t target;
  if (switec_getpos( id, &pos, &dir, &target )) {
    return luaL_error( L, "Unable to get position." );
  }
  lua_pushnumber(L, pos);
  lua_pushnumber(L, dir);
  return 2;
}

static int lswitec_dequeue(lua_State* L)
{
  int id;

  for (id = 0; id < SWITEC_CHANNEL_COUNT; id++) {
    if (stopped_callback[id] != LUA_NOREF) {
      int32_t pos;
      int32_t dir;
      int32_t target;
      if (!switec_getpos( id, &pos, &dir, &target )) {
	if (dir == 0 && pos == target) {
	  callback_execute(L, id);
	}
      }
    }
  }

  return 0;
}

static void lswitec_task(os_param_t param, uint8_t prio)
{
  (void) param;
  (void) prio;

  lswitec_dequeue(lua_getstate());
}

static int switec_open(lua_State *L)
{
  (void) L;

  tasknumber = task_get_id(lswitec_task);

  return 0;
}

// Module function map
static const LUA_REG_TYPE switec_map[] = {
  { LSTRKEY( "setup" ),    LFUNCVAL( lswitec_setup ) },
  { LSTRKEY( "close" ),    LFUNCVAL( lswitec_close ) },
  { LSTRKEY( "reset" ),    LFUNCVAL( lswitec_reset ) },
  { LSTRKEY( "moveto" ),   LFUNCVAL( lswitec_moveto) },
  { LSTRKEY( "getpos" ),   LFUNCVAL( lswitec_getpos) },
#ifdef SQITEC_DEBUG
  { LSTRKEY( "dequeue" ),  LFUNCVAL( lswitec_dequeue) },
#endif

  { LNILKEY, LNILVAL }
};

NODEMCU_MODULE(SWITEC, "switec", switec_map, switec_open);


text:
/**
 * Main file
 * Pokemon Showdown - http://pokemonshowdown.com/
 *
 * This is the main Pokemon Showdown app, and the file you should be
 * running to start Pokemon Showdown if you're using it normally.
 *
 * This file sets up our SockJS server, which handles communication
 * between users and your server, and also sets up globals. You can
 * see details in their corresponding files, but here's an overview:
 *
 * Users - from users.js
 *
 *   Most of the communication with users happens in users.js, we just
 *   forward messages between the sockets.js and users.js.
 *
 * Rooms - from rooms.js
 *
 *   Every chat room and battle is a room, and what they do is done in
 *   rooms.js. There's also a global room which every user is in, and
 *   handles miscellaneous things like welcoming the user.
 *
 * Tools - from tools.js
 *
 *   Handles getting data about Pokemon, items, etc. *
 *
 * Simulator - from simulator.js
 *
 *   Used to access the simulator itself.
 *
 * CommandParser - from command-parser.js
 *
 *   Parses text commands like /me
 *
 * Sockets - from sockets.js
 *
 *   Used to abstract out network connections. sockets.js handles
 *   the actual server and connection set-up.
 *
 * @license MIT license
 */

/*********************************************************
 * Make sure we have everything set up correctly
 *********************************************************/

// Make sure our dependencies are available, and install them if they
// aren't

function runNpm(command) {
	if (require.main !== module) throw new Error("Dependencies unmet");

	command = 'npm ' + command + ' && ' + process.execPath + ' app.js';
	console.log('Running `' + command + '`...');
	require('child_process').spawn('sh', ['-c', command], {stdio: 'inherit', detached: true});
	process.exit(0);
}

var isLegacyEngine = !global.Map;

var fs = require('fs');
var path = require('path');
try {
	require('sugar');
	if (isLegacyEngine) require('es6-shim');
} catch (e) {
	runNpm('install --production');
}
if (isLegacyEngine && !new Map().set()) {
	runNpm('update --production');
}

/*********************************************************
 * Load configuration
 *********************************************************/

try {
	global.Config = require('./config/config.js');
} catch (err) {
	if (err.code !== 'MODULE_NOT_FOUND') throw err;

	// Copy it over synchronously from config-example.js since it's needed before we can start the server
	console.log("config.js doesn't exist - creating one with default settings...");
	fs.writeFileSync(path.resolve(__dirname, 'config/config.js'),
		fs.readFileSync(path.resolve(__dirname, 'config/config-example.js'))
	);
	global.Config = require('./config/config.js');
}

if (Config.watchconfig) {
	fs.watchFile(path.resolve(__dirname, 'config/config.js'), function (curr, prev) {
		if (curr.mtime <= prev.mtime) return;
		try {
			delete require.cache[require.resolve('./config/config.js')];
			global.Config = require('./config/config.js');
			if (global.Users) Users.cacheGroupData();
			console.log('Reloaded config/config.js');
		} catch (e) {}
	});
}

// Autoconfigure the app when running in cloud hosting environments:
var cloudenv = require('cloud-env');
Config.bindaddress = cloudenv.get('IP', Config.bindaddress || '');
Config.port = cloudenv.get('PORT', Config.port);

if (require.main === module && process.argv[2] && parseInt(process.argv[2])) {
	Config.port = parseInt(process.argv[2]);
	Config.ssl = null;
}

global.ResourceMonitor = {
	connections: {},
	connectionTimes: {},
	battles: {},
	battleTimes: {},
	battlePreps: {},
	battlePrepTimes: {},
	networkUse: {},
	networkCount: {},
	cmds: {},
	cmdsTimes: {},
	cmdsTotal: {lastCleanup: Date.now(), count: 0},
	teamValidatorChanged: 0,
	teamValidatorUnchanged: 0,
	/**
	 * Counts a connection. Returns true if the connection should be terminated for abuse.
	 */
	log: function (text) {
		console.log(text);
		if (Rooms.rooms.staff) {
			Rooms.rooms.staff.add('||' + text);
			Rooms.rooms.staff.update();
		}
	},
	logHTML: function (text) {
		console.log(text);
		if (Rooms.rooms.staff) {
			Rooms.rooms.staff.add('|html|' + text);
			Rooms.rooms.staff.update();
		}
	},
	countConnection: function (ip, name) {
		var now = Date.now();
		var duration = now - this.connectionTimes[ip];
		name = (name ? ': ' + name : '');
		if (ip in this.connections && duration < 30 * 60 * 1000) {
			this.connections[ip]++;
			if (this.connections[ip] < 500 && duration < 5 * 60 * 1000 && this.connections[ip] % 30 === 0) {
				this.log('[ResourceMonitor] IP ' + ip + ' has connected ' + this.connections[ip] + ' times in the last ' + duration.duration() + name);
			} else if (this.connections[ip] < 500 && this.connections[ip] % 90 === 0) {
				this.log('[ResourceMonitor] IP ' + ip + ' has connected ' + this.connections[ip] + ' times in the last ' + duration.duration() + name);
			} else if (this.connections[ip] === 500) {
				this.log('[ResourceMonitor] IP ' + ip + ' has been banned for connection flooding (' + this.connections[ip] + ' times in the last ' + duration.duration() + name + ')');
				return true;
			} else if (this.connections[ip] > 500) {
				if (this.connections[ip] % 250 === 0) {
					this.log('[ResourceMonitor] Banned IP ' + ip + ' has connected ' + this.connections[ip] + ' times in the last ' + duration.duration() + name);
				}
				return true;
			}
		} else {
			this.connections[ip] = 1;
			this.connectionTimes[ip] = now;
		}
	},
	/**
	 * Counts a battle. Returns true if the connection should be terminated for abuse.
	 */
	countBattle: function (ip, name) {
		var now = Date.now();
		var duration = now - this.battleTimes[ip];
		name = (name ? ': ' + name : '');
		if (ip in this.battles && duration < 30 * 60 * 1000) {
			this.battles[ip]++;
			if (duration < 5 * 60 * 1000 && this.battles[ip] % 15 === 0) {
				this.log('[ResourceMonitor] IP ' + ip + ' has battled ' + this.battles[ip] + ' times in the last ' + duration.duration() + name);
			} else if (this.battles[ip] % 75 === 0) {
				this.log('[ResourceMonitor] IP ' + ip + ' has battled ' + this.battles[ip] + ' times in the last ' + duration.duration() + name);
			}
		} else {
			this.battles[ip] = 1;
			this.battleTimes[ip] = now;
		}
	},
	/**
	 * Counts battle prep. Returns true if too much
	 */
	countPrepBattle: function (ip) {
		var now = Date.now();
		var duration = now - this.battlePrepTimes[ip];
		if (ip in this.battlePreps && duration < 3 * 60 * 1000) {
			this.battlePreps[ip]++;
			if (this.battlePreps[ip] > 6) {
				return true;
			}
		} else {
			this.battlePreps[ip] = 1;
			this.battlePrepTimes[ip] = now;
		}
	},
	/**
	 * data
	 */
	countNetworkUse: function (size) {
		if (this.activeIp in this.networkUse) {
			this.networkUse[this.activeIp] += size;
			this.networkCount[this.activeIp]++;
		} else {
			this.networkUse[this.activeIp] = size;
			this.networkCount[this.activeIp] = 1;
		}
	},
	writeNetworkUse: function () {
		var buf = '';
		for (var i in this.networkUse) {
			buf += '' + this.networkUse[i] + '\t' + this.networkCount[i] + '\t' + i + '\n';
		}
		fs.writeFile(path.resolve(__dirname, 'logs/networkuse.tsv'), buf);
	},
	clearNetworkUse: function () {
		this.networkUse = {};
		this.networkCount = {};
	},
	/**
	 * Counts roughly the size of an object to have an idea of the server load.
	 */
	sizeOfObject: function (object) {
		var objectList = [];
		var stack = [object];
		var bytes = 0;

		while (stack.length) {
			var value = stack.pop();
			if (typeof value === 'boolean') bytes += 4;
			else if (typeof value === 'string') bytes += value.length * 2;
			else if (typeof value === 'number') bytes += 8;
			else if (typeof value === 'object' && objectList.indexOf(value) === -1) {
				objectList.push(value);
				for (var i in value) stack.push(value[i]);
			}
		}

		return bytes;
	},
	/**
	 * Controls the amount of times a cmd command is used
	 */
	countCmd: function (ip, name) {
		var now = Date.now();
		var duration = now - this.cmdsTimes[ip];
		name = (name ? ': ' + name : '');
		if (!this.cmdsTotal) this.cmdsTotal = {lastCleanup: 0, count: 0};
		if (now - this.cmdsTotal.lastCleanup > 60 * 1000) {
			this.cmdsTotal.count = 0;
			this.cmdsTotal.lastCleanup = now;
		}
		this.cmdsTotal.count++;
		if (ip in this.cmds && duration < 60 * 1000) {
			this.cmds[ip]++;
			if (duration < 60 * 1000 && this.cmds[ip] % 5 === 0) {
				if (this.cmds[ip] >= 3) {
					if (this.cmds[ip] % 30 === 0) this.log('CMD command from ' + ip + ' blocked for ' + this.cmds[ip] + 'th use in the last ' + duration.duration() + name);
					return true;
				}
				this.log('[ResourceMonitor] IP ' + ip + ' has used CMD command ' + this.cmds[ip] + ' times in the last ' + duration.duration() + name);
			} else if (this.cmds[ip] % 15 === 0) {
				this.log('CMD command from ' + ip + ' blocked for ' + this.cmds[ip] + 'th use in the last ' + duration.duration() + name);
				return true;
			}
		} else if (this.cmdsTotal.count > 8000) {
			// One CMD check per user per minute on average (to-do: make this better)
			this.log('CMD command for ' + ip + ' blocked because CMD has been used ' + this.cmdsTotal.count + ' times in the last minute.');
			return true;
		} else {
			this.cmds[ip] = 1;
			this.cmdsTimes[ip] = now;
		}
	}
};

/*********************************************************
 * Set up most of our globals
 *********************************************************/

/**
 * Converts anything to an ID. An ID must have only lowercase alphanumeric
 * characters.
 * If a string is passed, it will be converted to lowercase and
 * non-alphanumeric characters will be stripped.
 * If an object with an ID is passed, its ID will be returned.
 * Otherwise, an empty string will be returned.
 */
global.toId = function (text) {
	if (text && text.id) text = text.id;
	else if (text && text.userid) text = text.userid;

	return string(text).toLowerCase().replace(/[^a-z0-9]+/g, '');
};

/**
 * Sanitizes a username or Pokemon nickname
 *
 * Returns the passed name, sanitized for safe use as a name in the PS
 * protocol.
 *
 * Such a string must uphold these guarantees:
 * - must not contain any ASCII whitespace character other than a space
 * - must not start or end with a space character
 * - must not contain any of: | , [ ]
 * - must not be the empty string
 *
 * If no such string can be found, returns the empty string. Calling
 * functions are expected to check for that condition and deal with it
 * accordingly.
 *
 * toName also enforces that there are not multiple space characters
 * in the name, although this is not strictly necessary for safety.
 */
global.toName = function (name) {
	name = string(name);
	name = name.replace(/[\|\s\[\]\,]+/g, ' ').trim();
	if (name.length > 18) name = name.substr(0, 18).trim();
	return name;
};

/**
 * Safely ensures the passed variable is a string
 * Simply doing '' + str can crash if str.toString crashes or isn't a function
 * If we're expecting a string and being given anything that isn't a string
 * or a number, it's safe to assume it's an error, and return ''
 */
global.string = function (str) {
	if (typeof str === 'string' || typeof str === 'number') return '' + str;
	return '';
};

global.LoginServer = require('./loginserver.js');

global.Users = require('./users.js');

global.Rooms = require('./rooms.js');

delete process.send; // in case we're a child process
global.Verifier = require('./verifier.js');

global.CommandParser = require('./command-parser.js');

global.Simulator = require('./simulator.js');

global.Tournaments = require('./tournaments');

try {
	global.Dnsbl = require('./dnsbl.js');
} catch (e) {
	global.Dnsbl = {query:function () {}};
}

global.Cidr = require('./cidr.js');

if (Config.crashguard) {
	// graceful crash - allow current battles to finish before restarting
	var lastCrash = 0;
	process.on('uncaughtException', function (err) {
		var dateNow = Date.now();
		var quietCrash = require('./crashlogger.js')(err, 'The main process');
		quietCrash = quietCrash || ((dateNow - lastCrash) <= 1000 * 60 * 5);
		lastCrash = Date.now();
		if (quietCrash) return;
		var stack = ("" + err.stack).escapeHTML().split("\n").slice(0, 2).join("
");
		if (Rooms.lobby) {
			Rooms.lobby.addRaw('
THE SERVER HAS CRASHED: ' + stack + '
Please restart the server.
');
			Rooms.lobby.addRaw('
You will not be able to talk in the lobby or start new battles until the server restarts.
');
		}
		Config.modchat = 'crash';
		Rooms.global.lockdown = true;
	});
}

/*********************************************************
 * Start networking processes to be connected to
 *********************************************************/

global.Sockets = require('./sockets.js');

/*********************************************************
 * Set up our last global
 *********************************************************/

// This slow operation is done *after* we start listening for connections
// to the server. Anybody who connects while this require() is running will
// have to wait a couple seconds before they are able to join the server, but
// at least they probably won't receive a connection error message.
global.Tools = require('./tools.js');

// After loading tools, generate and cache the format list.
Rooms.global.formatListText = Rooms.global.getFormatListText();

global.TeamValidator = require('./team-validator.js');

// load ipbans at our leisure
fs.readFile(path.resolve(__dirname, 'config/ipbans.txt'), function (err, data) {
	if (err) return;
	data = ('' + data).split("\n");
	var rangebans = [];
	for (var i = 0; i < data.length; i++) {
		data[i] = data[i].split('#')[0].trim();
		if (!data[i]) continue;
		if (data[i].indexOf('/') >= 0) {
			rangebans.push(data[i]);
		} else if (!Users.bannedIps[data[i]]) {
			Users.bannedIps[data[i]] = '#ipban';
		}
	}
	Users.checkRangeBanned = Cidr.checker(rangebans);
});

/*********************************************************
 * Start up the REPL server
 *********************************************************/

require('./repl.js').start('app', function (cmd) { return eval(cmd); });

/*********************************************************
 * Load custom files
 *********************************************************/

global.Core = require('./core.js').core;

global.Components = require('./components.js');

global.Poll = require('./core.js').core.poll();

try {
	global.hangman = require('./hangman.js').hangman();
} catch (e) {
	console.log('Error loading hangman.js');
}


text:
#include "MetroSVG/Internal/LoggingUtils.h"

#include <CoreGraphics/CoreGraphics.h>

namespace metrosvg {
namespace internal {

std::string FormatArgs() {
  return "";
}

std::string FormatArgs(const LogArg &arg1) {
  return arg1.string_value();
}

std::string FormatArgs(const LogArg &arg1, const LogArg &arg2) {
  std::stringstream ss;
  ss << arg1.string_value() << ", " << arg2.string_value();
  return ss.str();
}

std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
                       const LogArg &arg3) {
  std::stringstream ss;
  ss << arg1.string_value() << ", " << arg2.string_value() << ", "
     << arg3.string_value();
  return ss.str();
}

std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
                       const LogArg &arg3, const LogArg &arg4) {
  std::stringstream ss;
  ss << arg1.string_value() << ", " << arg2.string_value() << ", "
     << arg3.string_value() << ", " << arg4.string_value();
  return ss.str();
}

std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
                       const LogArg &arg3, const LogArg &arg4,
                       const LogArg &arg5) {
  std::stringstream ss;
  ss << arg1.string_value() << ", " << arg2.string_value() << ", "
     << arg3.string_value() << ", " << arg4.string_value() << ", "
     << arg5.string_value();
  return ss.str();
}

std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
                       const LogArg &arg3, const LogArg &arg4,
                       const LogArg &arg5, const LogArg &arg6) {
  std::stringstream ss;
  ss << arg1.string_value() << ", " << arg2.string_value() << ", "
     << arg3.string_value() << ", " << arg4.string_value() << ", "
     << arg5.string_value() << ", " << arg6.string_value();
  return ss.str();
}

std::string FormatArgs(const LogArg &arg1, const LogArg &arg2,
                       const LogArg &arg3, const LogArg &arg4,
                       const LogArg &arg5, const LogArg &arg6,
                       const LogArg &arg7) {
  std::stringstream ss;
  ss << arg1.string_value() << ", " << arg2.string_value() << ", "
     << arg3.string_value() << ", " << arg4.string_value() << ", "
     << arg5.string_value() << ", " << arg6.string_value() << ", "
     << arg7.string_value();
  return ss.str();
}

template<>
std::string FormatValue(std::nullptr_t value) {
  return "NULL";
}

template<>
std::string FormatValue(const CGAffineTransform value) {
  std::stringstream ss;
  ss << "(" << value.a << ", " << value.b << ", "
     << value.c << ", " << value.d << ", "
     << value.tx << ", " << value.ty << ")";
  return ss.str();
}

template<>
std::string FormatValue(CGAffineTransform *value) {
  return FormatValue(*value);
}

template<>
std::string FormatValue(const CGPoint value) {
  std::stringstream ss;
  ss << "(" << value.x << ", " << value.y << ")";
  return ss.str();
}

template<>
std::string FormatValue(const CGRect value) {
  std::stringstream ss;
  ss << "(" << value.origin.x << ", " << value.origin.y << ", "
     << value.size.width << ", " << value.size.height << ")";
  return ss.str();
}

template<>
std::string FormatValue(CGLineCap value) {
  switch (value) {
    case kCGLineCapButt:
      return "kCGLineCapButt";
    case kCGLineCapRound:
      return "kCGLineCapRound";
    case kCGLineCapSquare:
      return "kCGLineCapSquare";
  }
}

template<>
std::string FormatValue(CGLineJoin value) {
  switch (value) {
    case kCGLineJoinMiter:
      return "kCGLineJoinMiter";
    case kCGLineJoinRound:
      return "kCGLineJoinRound";
    case kCGLineJoinBevel:
      return "kCGLineJoinBevel";
  }
}

}  // namespace internal
}  // namespace metrosvg


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"/>

    </android.support.v4.widget.SwipeRefreshLayout>

</RelativeLayout>


text:
<?php
 //WARNING: The contents of this file are auto-generated

$mod_strings = array_merge($mod_strings,
	array(
		 'LBL_SECURITYGROUPS_SUBPANEL_TITLE' => "Группы пользователей",
	)
);

 //WARNING: The contents of this file are auto-generated

//THIS FILE IS AUTO GENERATED, DO NOT MODIFY
$mod_strings['LBL_FP_EVENTS_PROSPECTS_1_FROM_FP_EVENTS_TITLE'] = 'События';

?>


text:
[[nodiscard]] auto
main() noexcept -> bsl::exit_code
{
    bsl::enable_color();

    bsl::ut_scenario{"verify noexcept"} = []() noexcept {
        bsl::ut_then{} = []() noexcept {
            static_assert(noexcept(mk::dispatch_syscall_bf_callback_op({})));
        };
    };

    return bsl::ut_success();
}


text:
#ifndef OS_DARWIN_IF_H
#define OS_DARWIN_IF_H

#if defined (__cplusplus)
extern "C" {
#endif

#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>

#define OS_API_EXPORT
#define OS_API_IMPORT

#if defined (__cplusplus)
}
#endif

#endif /* OS_DARWIN_IF_H */


text:
using System;
using System.Text;
using Kunukn.XmlVisual.Core.Entities;
using Kunukn.XmlVisual.Core.Utilities;
using Kunukn.XmlVisual.Core.Extensions;

namespace Kunukn.XmlVisual.Core.SvgBuilder.Factory
{
    // Introduction to information visualization page 66
    public class SvgMindMapBuilder : SvgBuilder
    {
        // singleton
        private static SvgBuilder _obj;
        private static readonly object Padlock = new object();
        private SvgMindMapBuilder() { }
        public static SvgBuilder Instance //thread safe
        {
            get
            {
                lock (Padlock)
                {
                    return _obj ?? (_obj = new SvgMindMapBuilder());
                }
            }
        }
        // end singleton

        //position of start
        private static int A = SvgTool.Width / 2;
        private static int B = SvgTool.Height / 2;

        public override SvgFile BuildSvg(XmlMetadata data)
        {
            this.UConfig = data.UConfig;
            data.IsViewImplemented = true;

            // Init element pos
            // The levels, set x,y pos for the elements

            Element root = null;
            foreach (var child in data.Root.Childs)
            {
                if (child.Type == XmlType.Node) //only 1 node, else invalid xml file
                    root = child;
            }

            if (root != null)
            {
                root.Type = XmlType.Root;
                double sizex = SvgTool.ElementWidth;
                double sizey = SvgTool.ElementHeight;

                root.Svg.Width = sizex.ToIntRounded();
                root.Svg.Height = sizey.ToIntRounded();
                root.Svg.X = A;
                root.Svg.Y = B;
                var m = new MindmapData();
                m.ThetaLeftRestrict = 0;
                m.ThetaRightRestrict = MathTool.Pi2 - MathTool.AngleToRadian(1);//MathTool.Epsilon;
                root.Svg.ViewData = m;

                if (root.HasChildren())
                    DoCalculation(root, data);
            }

            // GENERATE SVG
            var svg = new SvgFile(this.UConfig);
            var sb = new StringBuilder();
            var title = string.Format("{0}", UConfig.GetSvgTitle());
            data.Title = title;
            sb.Append(string.Format("<title>{0}</title>" + NL, title));

            if (UConfig.IncludeBigraph)
                data.BigraphInfo = "No Bigraph for this view";

            sb.Append(SvgTool.GetMetaText(data));

            sb.Append(string.Format("<g id='viewport'>")); sb.Append(" <!-- viewport -->" + NL);
            sb.Append(string.Format("<g id='structure'>")); sb.Append(" <!-- structure -->" + NL);

            var recursiveGroupBuilded = new StringBuilder();
            RecursiveCreateElementGroup(root, recursiveGroupBuilded);
            sb.Append(recursiveGroupBuilded.ToString());

            sb.Append("</g>"); sb.Append(" <!-- end structure -->" + NL);

            sb.Append("</g>"); sb.Append(" <!-- end viewport -->" + NL + NL);
            svg.GraphicContent = sb.ToString();

            return svg;
        }

        public void RecursiveCreateElementGroup(Element node, StringBuilder sb)
        {
            if (node == null || node.Svg.Width == 0)
                return;

            // pre recursive work
            sb.Append(CreateElementGroup(node, 0, 0));
            bool hasChildren = !node.IsLeaf();
            if (hasChildren)
            {
                sb.Append(string.Format("<g id='subgn{0}' style=''>{1}", node.Id, NL));

                // Lines
                var childs = node.Childs;
                if (childs.Count > 0)
                    foreach (var child in childs)
                    {
                        if (child.Svg.Width == 0)
                            continue;

                        var px = node.Svg.X + node.Svg.Width / 2;
                        var py = node.Svg.Y + node.Svg.Height / 2;
                        var cx = child.Svg.X + child.Svg.Width / 2;
                        var cy = child.Svg.Y + child.Svg.Height / 2;
                        sb.Append(String.Format("<line x1='{0}' y1='{1}' x2='{2}' y2='{3}' class='Line2'/>{4}", px, py, cx, cy, NL));
                    }
            }

            // recursive work
            foreach (var child in node.Childs)
                RecursiveCreateElementGroup(child, sb);

            // post recursive work
            if (hasChildren)
            {
                sb.Append(string.Format("</g>" + NL));
            }
        }

        /// <summary>
        /// Heuristic approach
        /// </summary>
        /// <param name="theta"></param>
        /// <param name="items"></param>
        /// <param name="isLeaf"></param>
        /// <returns></returns>
        static double GetRadiusNeeded(double theta, int items, bool isLeaf)
        {
            double def = SvgTool.ElementWidth * 1.9; // default length between parent and child line

            int span = (SvgTool.ElementWidth * 1.4).ToIntRounded(); // default span dist between childs
            var degree = MathTool.RadiansToAngle(theta);
            var degreeHalf = degree / 2.0;
            var thetaHalf = MathTool.RadianNormalize(theta / 2.0);

            if (degree >= 70 || items <= 1) // wide enough, return something smaller than def
                return def / 1.4;

            if (degree >= 40) // wide enough
                return def;

            if (degreeHalf < 2)
                thetaHalf = MathTool.AngleToRadian(2);

            // triangle trigonometri
            var sin = Math.Abs(Math.Sin(thetaHalf)); //MathTool.RadianNormalize(sin);

            var c = def;
            var b = sin * c;

            int i = 0;
            while (b * 2 < span)
            {
                if (i++ >= 20) // stop here reduce len even angle is to small to display evenly
                    break;
                c += def;
                b = sin * c;
            }

            if(c<0)
                throw new Exception();

            return c;
        }

        /// <summary>
        /// Heuristic approach, the fn could be simpler but has been tweaked a few places for experimenting
        /// Sunburst imple is much simpler
        /// </summary>
        /// <param name="root"></param>
        /// <param name="data"></param>
        static void DoCalculation(Element root, XmlMetadata data)
        {
            var childs = root.Childs;
            var count = childs.Count;

            //http://en.wikipedia.org/wiki/Polar_coordinate_system
            // first child points downward, even distribute

            double beg = MathTool.AngleToRadian(90);

            double thetaRootStep = count == 0 ? 0 : MathTool.Pi2 / count;

            // init root children
            for (int i = 0; i < count; i++)
            {
                var c = childs[i];

                var d = new MindmapData();
                d.ThetaPoint = i * thetaRootStep + beg;

                if (count >= 3)
                {
                    d.ThetaLeftRestrict = (i - 1) * thetaRootStep + beg;
                    d.ThetaRightRestrict = (i + 1) * thetaRootStep + beg;
                }
                else if (count == 2)
                {
                    d.ThetaLeftRestrict = d.ThetaPoint - MathTool.Pihalf;
                    d.ThetaRightRestrict = d.ThetaPoint + MathTool.Pihalf;
                }
                else
                {
                    d.ThetaLeftRestrict = d.ThetaPoint - MathTool.Pihalf;
                    d.ThetaRightRestrict = d.ThetaPoint + MathTool.Pihalf;
                }

                d.Radius = GetRadiusNeeded(thetaRootStep, count, c.IsLeaf());
                c.Svg.ViewData = d;

                c.Svg.Width = SvgTool.ElementWidth;
                c.Svg.Height = SvgTool.ElementHeight;
                double x, y;
                MathTool.PolarToCartesian(d.ThetaPoint, d.Radius, out x, out y);
                c.Svg.X = x.ToIntRounded() + A;
                c.Svg.Y = y.ToIntRounded() + B;

                var debug = c.Name + " " + d.Debug;
            }

            // init rest layers
            for (int i = 2; i <= data.Height; i++)
            {

                // UPDATE RESTRICT
                var level = data.GetLevel(i);
                for (int j = 0; j < level.Count; j++)
                {
                    Element current = level[j];
                    Element left = null;
                    Element right = null;
                    const double aloneSpan = MathTool.Pihalf / 1.1;

                    if (level.Count >= 3)
                    {
                        left = j == 0 ? level[level.Count - 1] : level[j - 1];
                        right = j == level.Count - 1 ? level[0] : level[j + 1];
                    }

                    var d = current.Svg.ViewData as MindmapData;

                    if (level.Count == 1)
                    {
                        // alone, increase span
                        d.ThetaLeftRestrict = d.ThetaPoint - aloneSpan;
                        d.ThetaRightRestrict = d.ThetaPoint + aloneSpan;
                    }
                    else if (level.Count == 2)
                    {
                        var other = j == 0 ? level[1] : level[0];
                        if (other.IsLeaf())
                        {
                            d.ThetaLeftRestrict = d.ThetaPoint - aloneSpan;
                            d.ThetaRightRestrict = d.ThetaPoint + aloneSpan;
                        }
                        else
                        {
                            var otherm = other.Svg.ViewData as MindmapData;
                            double distr = MathTool.DistanceRadian(d.ThetaPoint, otherm.ThetaPoint);
                            double distl = MathTool.DistanceRadian(otherm.ThetaPoint, d.ThetaPoint);
                            d.ThetaRightRestrict = d.ThetaPoint + distr / 2;
                            d.ThetaLeftRestrict = d.ThetaPoint - distl / 2;
                        }

                    }
                    else
                    {
                        var leftm = left.Svg.ViewData as MindmapData;
                        var rightm = right.Svg.ViewData as MindmapData;

                        if (left.IsLeaf())
                            // might collide using Math.PI/8 but reduce size
                            d.ThetaLeftRestrict = leftm.ThetaPoint - Math.PI / 8;//leftm.ThetaPoint;
                        else
                        {
                            double distl = MathTool.DistanceRadian(leftm.ThetaPoint, d.ThetaPoint);
                            d.ThetaLeftRestrict = d.ThetaPoint - distl / 2;
                        }

                        if (right.IsLeaf())
                            // might collide using Math.PI/8 but reduce size
                            d.ThetaRightRestrict = rightm.ThetaPoint + Math.PI / 8;//rightm.ThetaPoint
                        else
                        {
                            double distr = MathTool.DistanceRadian(d.ThetaPoint, rightm.ThetaPoint);
                            d.ThetaRightRestrict = d.ThetaPoint + distr / 2;
                        }

                    }

                    // restrict by max span of left, only by 90 angle related to Thetapoint or if alone
                    var dist = MathTool.DistanceRadian(d.ThetaLeftRestrict, d.ThetaPoint);
                    if (dist > MathTool.Pihalf + MathTool.Epsilon)
                        d.ThetaLeftRestrict = d.ThetaPoint - aloneSpan;

                    // restrict by max span of right, only by 90 angle related to Thetapoint or if alone
                    dist = MathTool.DistanceRadian(d.ThetaPoint, d.ThetaRightRestrict);
                    if (dist > MathTool.Pihalf + MathTool.Epsilon)
                        d.ThetaRightRestrict = d.ThetaPoint + aloneSpan;
                }

                // INIT LAYER and set children mindmap data
                for (int j = 0; j < level.Count; j++)
                {
                    Element current = level[j];
                    var pd = current.Svg.ViewData as MindmapData;
                    double thetaStep = MathTool.DistanceRadian(pd.ThetaLeftRestrict, pd.ThetaRightRestrict); //Math.PI; //default
                    if (current.Childs.Count > 1)
                        thetaStep = MathTool.DistanceRadian(pd.ThetaLeftRestrict, pd.ThetaRightRestrict) / (current.Childs.Count - 1);

                    for (int k = 0; k < current.Childs.Count; k++)
                    {
                        var c = current.Childs[k];
                        var d = new MindmapData();

                        // placement
                        if (current.Childs.Count == 1)
                        {
                            d.ThetaPoint = pd.ThetaPoint;
                            d.ThetaLeftRestrict = pd.ThetaLeftRestrict;
                            d.ThetaRightRestrict = pd.ThetaRightRestrict;
                        }
                        else //count > 1
                        {
                            d.ThetaPoint = k * thetaStep + pd.ThetaLeftRestrict;
                            if (k == 0)
                            {
                                d.ThetaLeftRestrict = pd.ThetaLeftRestrict;
                                d.ThetaRightRestrict = pd.ThetaLeftRestrict + thetaStep;
                            }
                            else if (k == current.Childs.Count - 1)
                            {
                                d.ThetaRightRestrict = pd.ThetaRightRestrict;
                                d.ThetaLeftRestrict = pd.ThetaRightRestrict - thetaStep;
                            }
                            else
                            {
                                d.ThetaLeftRestrict = (k - 1) * thetaStep + pd.ThetaLeftRestrict;
                                d.ThetaRightRestrict = (k + 1) * thetaStep + pd.ThetaLeftRestrict;
                            }

                        }

                        d.Radius = GetRadiusNeeded(thetaStep, current.Childs.Count, c.IsLeaf());
                        c.Svg.ViewData = d;

                        c.Svg.Width = SvgTool.ElementWidth;
                        c.Svg.Height = SvgTool.ElementHeight;
                        double x, y;
                        MathTool.PolarToCartesian(d.ThetaPoint, d.Radius, out x, out y);
                        c.Svg.X = x.ToIntRounded() + c.Parent.Svg.X;
                        c.Svg.Y = y.ToIntRounded() + c.Parent.Svg.Y;
                    }
                }

            }
        }

        string CreateElementGroup(Element e, int xoffset, int yoffset)
        {
            if (e == null)
                return string.Empty;
            var gb = string.Format("<g id='gn{0}' onmouseover='HItem(evt)' onmouseout='UItem(evt)' onclick='g{1}(evt)'>{2}", e.Id, this.UConfig.JsGroupFn, NL);
            Box b = new Box(xoffset, yoffset, e);
            var ge = "</g>" + NL;
            var g = gb + b.GetSvg(this.UConfig) + ge;
            return g;
        }

    }
}


text:
001
016
017    package com.google.common.collect;
018
019    import static com.google.common.base.Preconditions.checkArgument;
020
021    import com.google.common.annotations.GwtCompatible;
022    import com.google.common.annotations.GwtIncompatible;
023    import com.google.common.annotations.VisibleForTesting;
024
025    import java.io.IOException;
026    import java.io.ObjectInputStream;
027    import java.io.ObjectOutputStream;
028    import java.util.ArrayList;
029    import java.util.Collection;
030    import java.util.HashMap;
031    import java.util.List;
032    import java.util.Map;
033
034    /**
035     * Implementation of {@code Multimap} that uses an {@code ArrayList} to store
036     * the values for a given key. A {@link HashMap} associates each key with an
037     * {@link ArrayList} of values.
038     *
039     * <p>When iterating through the collections supplied by this class, the
040     * ordering of values for a given key agrees with the order in which the values
041     * were added.
042     *
043     * <p>This multimap allows duplicate key-value pairs. After adding a new
044     * key-value pair equal to an existing key-value pair, the {@code
045     * ArrayListMultimap} will contain entries for both the new value and the old
046     * value.
047     *
048     * <p>Keys and values may be null. All optional multimap methods are supported,
049     * and all returned views are modifiable.
050     *
051     * <p>The lists returned by {@link #get}, {@link #removeAll}, and {@link
052     * #replaceValues} all implement {@link java.util.RandomAccess}.
053     *
054     * <p>This class is not threadsafe when any concurrent operations update the
055     * multimap. Concurrent read operations will work correctly. To allow concurrent
056     * update operations, wrap your multimap with a call to {@link
057     * Multimaps#synchronizedListMultimap}.
058     *
059     * @author Jared Levy
060     * @since 2 (imported from Google Collections Library)
061     */
062    @GwtCompatible(serializable = true, emulated = true)
063    public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
064      // Default from ArrayList
065      private static final int DEFAULT_VALUES_PER_KEY = 10;
066
067      @VisibleForTesting transient int expectedValuesPerKey;
068
069      /**
070       * Creates a new, empty {@code ArrayListMultimap} with the default initial
071       * capacities.
072       */
073      public static <K, V> ArrayListMultimap<K, V> create() {
074        return new ArrayListMultimap<K, V>();
075      }
076
077      /**
078       * Constructs an empty {@code ArrayListMultimap} with enough capacity to hold
079       * the specified numbers of keys and values without resizing.
080       *
081       * @param expectedKeys the expected number of distinct keys
082       * @param expectedValuesPerKey the expected average number of values per key
083       * @throws IllegalArgumentException if {@code expectedKeys} or {@code
084       *      expectedValuesPerKey} is negative
085       */
086      public static <K, V> ArrayListMultimap<K, V> create(
087          int expectedKeys, int expectedValuesPerKey) {
088        return new ArrayListMultimap<K, V>(expectedKeys, expectedValuesPerKey);
089      }
090
091      /**
092       * Constructs an {@code ArrayListMultimap} with the same mappings as the
093       * specified multimap.
094       *
095       * @param multimap the multimap whose contents are copied to this multimap
096       */
097      public static <K, V> ArrayListMultimap<K, V> create(
098          Multimap<? extends K, ? extends V> multimap) {
099        return new ArrayListMultimap<K, V>(multimap);
100      }
101
102      private ArrayListMultimap() {
103        super(new HashMap<K, Collection<V>>());
104        expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
105      }
106
107      private ArrayListMultimap(int expectedKeys, int expectedValuesPerKey) {
108        super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(expectedKeys));
109        checkArgument(expectedValuesPerKey >= 0);
110        this.expectedValuesPerKey = expectedValuesPerKey;
111      }
112
113      private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
114        this(multimap.keySet().size(),
115            (multimap instanceof ArrayListMultimap) ?
116                ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey :
117                DEFAULT_VALUES_PER_KEY);
118        putAll(multimap);
119      }
120
121      /**
122       * Creates a new, empty {@code ArrayList} to hold the collection of values for
123       * an arbitrary key.
124       */
125      @Override List<V> createCollection() {
126        return new ArrayList<V>(expectedValuesPerKey);
127      }
128
129      /**
130       * Reduces the memory used by this {@code ArrayListMultimap}, if feasible.
131       */
132      public void trimToSize() {
133        for (Collection<V> collection : backingMap().values()) {
134          ArrayList<V> arrayList = (ArrayList<V>) collection;
135          arrayList.trimToSize();
136        }
137      }
138
139      /**
140       * @serialData expectedValuesPerKey, number of distinct keys, and then for
141       *     each distinct key: the key, number of values for that key, and the
142       *     key's values
143       */
144      @GwtIncompatible("java.io.ObjectOutputStream")
145      private void writeObject(ObjectOutputStream stream) throws IOException {
146        stream.defaultWriteObject();
147        stream.writeInt(expectedValuesPerKey);
148        Serialization.writeMultimap(this, stream);
149      }
150
151      @GwtIncompatible("java.io.ObjectOutputStream")
152      private void readObject(ObjectInputStream stream)
153          throws IOException, ClassNotFoundException {
154        stream.defaultReadObject();
155        expectedValuesPerKey = stream.readInt();
156        int distinctKeys = Serialization.readCount(stream);
157        Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
158        setMap(map);
159        Serialization.populateMultimap(this, stream, distinctKeys);
160      }
161
162      @GwtIncompatible("Not needed in emulated source.")
163      private static final long serialVersionUID = 0;
164    }