using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;

using Anticutan.Data.Attachments;
using Anticutan.Data.Entries;

using VkNet;
using VkNet.Categories;
using VkNet.Enums.Filters;
using VkNet.Enums.SafetyEnums;
using VkNet.Exception;
using VkNet.Model;
using VkNet.Model.Attachments;
using VkNet.Model.RequestParams;
using VkNet.Utils;

namespace Anticutan.Data
{
    internal static class VkApiWrapper
    {
        /// <summary>
        /// Количество попыток отправки запроса API ВКонтакте.
        /// </summary>
        private const byte AttemptCount = byte.MaxValue;

        /// <summary>
        /// Время задержки после неудачного запроса API ВКонтакте.
        /// </summary>
        private const int MillisecondsDelay = 1000;

        /// <summary>
        /// Возвращает список комментариев в указанном обсуждении.
        /// </summary>
        /// <param name="boardCategory"></param>
        /// <param name="groupId">Идентификатор сообщества, информацию об обсуждениях которого нужно получить.</param>
        /// <param name="topicId">Идентификатор обсуждения.</param>
        /// <param name="offset">Смещение, необходимое для выборки определенного подмножества комментариев.</param>
        /// <param name="count">Количество сообщений, которое необходимо получить. Максимальное значение: 100.</param>
        /// <returns></returns>
        private static ReadOnlyCollection<Comment> BoardGetComments(BoardCategory boardCategory, long groupId, long topicId, int offset, int count)
        {
            if (boardCategory == null) return null;

            groupId = Math.Abs(groupId);
            byte b = 0;
            do
            {
                try
                {
                    return boardCategory.GetComments(new BoardGetCommentsParams
                                                     {
                                                         GroupId = groupId,
                                                         TopicId = topicId,
                                                         Offset = offset,
                                                         Count = count,
                                                         NeedLikes = true
                                                     })?.Items;
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }

        /// <summary>
        /// Возвращает список обсуждений указанного сообщества.
        /// </summary>
        /// <param name="boardCategory"></param>
        /// <param name="groupId">
        /// Идентификатор сообщества, информацию об обсуждениях которого необходимо получить.
        /// Если сообщество закрытое или частное, для вызова метода потребуется право доступа groups.
        /// </param>
        /// <param name="offset">Смещение, необходимое для выборки определенного подмножества обсуждений.</param>
        /// <param name="count">Количество обсуждений, которое необходимо получить. Максимальное значение: 100.</param>
        private static VkCollection<Topic> BoardGetTopics(BoardCategory boardCategory, long groupId, int offset, int count)
        {
            if (boardCategory == null) return null;

            groupId = Math.Abs(groupId);
            byte b = 0;
            do
            {
                try
                {
                    return boardCategory.GetTopics(new BoardGetTopicsParams {GroupId = groupId, Offset = offset, Count = count});
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }

        private static List<ContactComment> ConvertCommentsToContactComments(IReadOnlyCollection<Comment> comments,
                                                                             VkApi api,
                                                                             long groupId,
                                                                             LikeObjectType likeObjectType)
        {
            var contactComments = new List<ContactComment>();
            if (comments == null) return contactComments;

            foreach (Comment comment in comments)
            {
                if (comment == null) continue;

                long commentId = comment.Id;

                List<ContactAttachment> commentContactAttachments = GetContactAttachments(api, comment.Attachments, commentId);

                HashSet<long> commentLikeUserIds = comment.Likes == null || comment.Likes.Count > 0
                                                       ? GetLikeUserIds(api?.Likes, groupId, commentId, likeObjectType)
                                                       : new HashSet<long>();

                var contactComment = new ContactComment(commentId,
                                                        comment.Text,
                                                        comment.FromId,
                                                        commentContactAttachments,
                                                        commentLikeUserIds,
                                                        comment.Date,
                                                        comment.ReplyToCommentId,
                                                        comment.ReplyToUserId);
                contactComments.Add(contactComment);
            }
            return contactComments;
        }

        private static List<ContactAttachment> GetContactAttachments(VkApi api, IReadOnlyCollection<Attachment> attachments, long? postId)
        {
            var contactAttachments = new List<ContactAttachment>();
            if (attachments == null) return contactAttachments;

            foreach (Attachment attachment in attachments)
            {
                if (attachment == null) continue;

                if (attachment.Type == typeof(Photo))
                {
                    if (attachment.Instance is Photo photo)
                    {
                        var contactPhoto = new ContactPhoto(photo.Id,
                                                            photo.OwnerId,
                                                            photo.AlbumId,
                                                            photo.Photo75,
                                                            photo.Photo130,
                                                            photo.Photo604,
                                                            photo.Photo807,
                                                            photo.Photo1280,
                                                            photo.Photo2560,
                                                            photo.Width,
                                                            photo.Height,
                                                            photo.Text,
                                                            photo.CreateTime,
                                                            photo.UserId,
                                                            photo.PostId,
                                                            photo.AccessKey,
                                                            photo.PhotoSrc,
                                                            photo.PhotoHash,
                                                            photo.SmallPhotoSrc,
                                                            photo.BigPhotoSrc,
                                                            photo.Latitude,
                                                            photo.Longitude);
                        contactAttachments.Add(contactPhoto);
                    }
                }
                else if (attachment.Type == typeof(Poll))
                {
                    if (attachment.Instance is Poll poll)
                    {
                        int voteCount = poll.Votes ?? 0;

                        var contactAnswers = new List<ContactPollAnswer>();
                        Collection<PollAnswer> answers = poll.Answers;
                        if (answers != null)
                        {
                            var answerIds = new HashSet<long>();
                            foreach (PollAnswer answer in answers)
                            {
                                long? answerId = answer?.Id;
                                if (!answerId.HasValue) continue;

                                answerIds.Add(answerId.Value);
                            }

                            long? ownerId = poll.OwnerId;
                            long? pollId = poll.Id;
                            bool isAnonymous = poll.IsAnonymous ?? false;

                            List<PollAnswerVoters> voters;
                            if (ownerId.HasValue && pollId.HasValue && answerIds.Count > 0 && voteCount > 0 && !isAnonymous)
                            {
                                voters = GetVoters(api.PollsCategory, ownerId.Value, postId.Value, pollId.Value, answerIds.ToList());
                            }
                            else
                            {
                                voters = new List<PollAnswerVoters>();
                            }

                            var votedUserIdsDict = new Dictionary<long, HashSet<long>>();
                            foreach (PollAnswerVoters voter in voters)
                            {
                                long? answerId = voter?.AnswerId;
                                if (!answerId.HasValue) continue;

                                VkCollection<long> userIds = voter.UsersIds;
                                if (userIds == null) continue;

                                if (votedUserIdsDict.ContainsKey(answerId.Value))
                                {
                                    HashSet<long> votedUserIds = votedUserIdsDict[answerId.Value];

                                    int i = 0;
                                    while (votedUserIds.Count < int.MaxValue && i < userIds.Count)
                                    {
                                        votedUserIds.Add(userIds[i]);
                                        i++;
                                    }
                                }
                                else
                                {
                                    votedUserIdsDict.Add(answerId.Value, new HashSet<long>(userIds));
                                }
                            }

                            foreach (PollAnswer answer in answers)
                            {
                                long? answerId = answer?.Id;
                                if (!answerId.HasValue) continue;

                                HashSet<long> votedUserIds = votedUserIdsDict.ContainsKey(answerId.Value)
                                                                 ? votedUserIdsDict[answerId.Value]
                                                                 : new HashSet<long>();

                                var contactAnswer = new ContactPollAnswer(answer.Id, answer.Text, answer.Votes, answer.Rate, votedUserIds);
                                contactAnswers.Add(contactAnswer);
                            }
                        }

                        var contactPoll = new ContactPoll(poll.Id, poll.OwnerId, poll.Question, poll.Created, voteCount, poll.IsAnonymous, contactAnswers);
                        contactAttachments.Add(contactPoll);
                    }
                }
            }
            return contactAttachments;
        }

        public static List<ContactPost> GetContactPosts(VkApi api, long groupId, uint? count = null)
        {
            var contactPosts = new List<ContactPost>();
            if (api == null) return contactPosts;

            List<Post> posts = GetPosts(api.Wall, groupId, count);
            if (posts.Count <= 0) return contactPosts;

            foreach (Post post in posts)
            {
                long? postId = post?.Id;
                if (!postId.HasValue) continue;

                long? fromId = post.FromId;
                if (!fromId.HasValue) continue;

                List<ContactAttachment> postContactAttachments = GetContactAttachments(api, post.Attachments, postId);

                List<Comment> comments = post.Comments == null || post.Comments.Count > 0
                                             ? GetPostComments(api.Wall, groupId, postId.Value)
                                             : new List<Comment>();
                List<ContactComment> contactComments = ConvertCommentsToContactComments(comments, api, groupId, LikeObjectType.Comment);

                HashSet<long> postLikeUserIds = post.Likes == null || post.Likes.Count > 0
                                                    ? GetLikeUserIds(api.Likes, groupId, postId.Value, LikeObjectType.Post)
                                                    : new HashSet<long>();

                var contactPost = new ContactPost(postId.Value, post.Text, fromId.Value, post.Date, postContactAttachments, postLikeUserIds, contactComments);
                contactPosts.Add(contactPost);
            }
            return contactPosts;
        }

        public static List<ContactTopic> GetContactTopics(VkApi api, long groupId)
        {
            var contactTopics = new List<ContactTopic>();
            if (api == null) return contactTopics;

            List<Topic> topics = GetTopics(api.Board, groupId);
            if (topics.Count <= 0) return contactTopics;

            foreach (Topic topic in topics)
            {
                if (topic == null) continue;

                long topicId = topic.Id;

                List<Comment> comments = GetTopicComments(api.Board, groupId, topicId);
                List<ContactComment> contactComments = ConvertCommentsToContactComments(comments, api, groupId, LikeObjectType.TopicComment);

                var contactTopic = new ContactTopic(topicId,
                                                    topic.Title,
                                                    topic.Сreated,
                                                    topic.СreatedBy,
                                                    topic.IsClosed,
                                                    topic.IsFixed,
                                                    contactComments);
                contactTopics.Add(contactTopic);
            }
            return contactTopics;
        }

        public static List<User> GetGroupMembers(GroupsCategory groupsCategory, long groupId)
        {
            var members = new List<User>();
            if (groupsCategory == null) return members;

            int offset = 0;
            const int count = 1000;
            do
            {
                VkCollection<User> data = GroupsGetMembers(groupsCategory, groupId, offset, count);
                if (data == null || data.Count <= 0) break;

                int i = 0;
                while (members.Count < int.MaxValue && i < data.Count)
                {
                    members.Add(data[i]);
                    i++;
                }

                if (data.Count < count) break;
                try
                {
                    offset = checked(offset + count);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    break;
                }
            } while (offset <= members.Count);
            return members;
        }

        private static HashSet<long> GetLikeUserIds(LikesCategory likesCategory, long ownerId, long likeObjectId, LikeObjectType likeObjectType)
        {
            var userIds = new HashSet<long>();
            if (likesCategory == null) return userIds;

            int offset = 0;
            const int count = 1000;
            do
            {
                VkCollection<long> data = LikesGetList(likesCategory, ownerId, likeObjectId, likeObjectType, offset, count);
                if (data == null || data.Count <= 0) break;

                int i = 0;
                while (userIds.Count < int.MaxValue && i < data.Count)
                {
                    userIds.Add(data[i]);
                    i++;
                }

                if (data.Count < count) break;
                try
                {
                    offset = checked(offset + count);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    break;
                }
            } while (offset <= userIds.Count);
            return userIds;
        }

        private static List<Comment> GetPostComments(WallCategory wallCategory, long ownerId, long postId)
        {
            var comments = new List<Comment>();
            if (wallCategory == null) return comments;

            int offset = 0;
            const int count = 100;
            do
            {
                VkCollection<Comment> data = WallGetComments(wallCategory, ownerId, postId, offset, count);
                if (data == null || data.Count <= 0) break;

                int i = 0;
                while (comments.Count < int.MaxValue && i < data.Count)
                {
                    comments.Add(data[i]);
                    i++;
                }

                if (data.Count < count) break;
                try
                {
                    offset = checked(offset + count);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    break;
                }
            } while (offset <= comments.Count);
            return comments;
        }

        private static List<Post> GetPosts(WallCategory wallCategory, long ownerId, uint? number)
        {
            var posts = new List<Post>();
            if (wallCategory == null || number == 0) return posts;

            int offset = 0;
            const int count = 100;
            do
            {
                ReadOnlyCollection<Post> data = WallGet(wallCategory, ownerId, offset, count)?.WallPosts;
                if (data == null || data.Count <= 0) break;

                int i = 0;
                while (posts.Count < int.MaxValue && i < data.Count && posts.Count != number)
                {
                    posts.Add(data[i]);
                    i++;
                }

                if (data.Count < count) break;
                try
                {
                    offset = checked(offset + count);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    break;
                }
            } while (offset <= posts.Count && posts.Count != number);
            return posts;
        }

        private static List<Comment> GetTopicComments(BoardCategory boardCategory, long groupId, long topicId)
        {
            var comments = new List<Comment>();
            if (boardCategory == null) return comments;

            int offset = 0;
            const int count = 100;
            do
            {
                ReadOnlyCollection<Comment> data = BoardGetComments(boardCategory, groupId, topicId, offset, count);
                if (data == null || data.Count <= 0) break;

                int i = 0;
                while (comments.Count < int.MaxValue && i < data.Count)
                {
                    comments.Add(data[i]);
                    i++;
                }

                if (data.Count < count) break;
                try
                {
                    offset = checked(offset + count);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    break;
                }
            } while (offset <= comments.Count);
            return comments;
        }

        private static List<Topic> GetTopics(BoardCategory boardCategory, long groupId)
        {
            var topics = new List<Topic>();
            if (boardCategory == null) return topics;

            int offset = 0;
            const int count = 100;
            do
            {
                VkCollection<Topic> data = BoardGetTopics(boardCategory, groupId, offset, count);
                if (data == null || data.Count <= 0) break;

                int i = 0;
                while (topics.Count < int.MaxValue && i < data.Count)
                {
                    topics.Add(data[i]);
                    i++;
                }

                if (data.Count < count) break;
                try
                {
                    offset = checked(offset + count);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    break;
                }
            } while (offset <= topics.Count);
            return topics;
        }

        public static List<User> GetUsers(UsersCategory usersCategory, HashSet<long> userIds)
        {
            var users = new List<User>();
            if (usersCategory == null || userIds == null || userIds.Count <= 0) return users;

            var current = new HashSet<long>();
            var blocks = new List<HashSet<long>> {current};
            foreach (long userId in userIds)
            {
                current.Add(userId);
                if (current.Count == 1000)
                {
                    current = new HashSet<long>();
                    blocks.Add(current);
                }
            }

            foreach (HashSet<long> ids in blocks)
            {
                ReadOnlyCollection<User> list = UsersGet(usersCategory, ids);
                if (list == null) continue;

                users.AddRange(list);
            }

            return users;
        }

        private static List<PollAnswerVoters> GetVoters(PollsCategory pollsCategory, long ownerId, long postId, long pollId, List<long> answerIds)
        {
            var voters = new List<PollAnswerVoters>();
            if (pollsCategory == null) return voters;

            int offset = 0;
            const int count = 1000;
            do
            {
                VkCollection<PollAnswerVoters> data = PollsGetVoters(postId, pollsCategory, ownerId, pollId, answerIds, offset, count);
                if (data == null || data.Count <= 0) break;

                int i = 0;
                while (voters.Count < int.MaxValue && i < data.Count)
                {
                    voters.Add(data[i]);
                    i++;
                }

                int userCount = 0;
                foreach (PollAnswerVoters item in data)
                {
                    VkCollection<long> userIds = item?.UsersIds;
                    if (userIds == null) continue;

                    try
                    {
                        userCount = checked(userCount + userIds.Count);
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                        return voters;
                    }
                }

                if (userCount < count) break;
                try
                {
                    offset = checked(offset + userCount);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    break;
                }
            } while (voters.Count < int.MaxValue);
            return voters;
        }

        private static VkCollection<User> GroupsGetMembers(GroupsCategory groupsCategory, long groupId, int offset, int count)
        {
            if (groupsCategory == null) return null;

            groupId = Math.Abs(groupId);
            byte b = 0;
            do
            {
                try
                {
                    return groupsCategory.GetMembers(new GroupsGetMembersParams {GroupId = groupId.ToString(), Offset = offset, Count = count});
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }

        /// <summary>
        /// Возвращает список идентификаторов пользователей, добавивших заданный объект в свой список "Мне нравится".
        /// </summary>
        /// <param name="likesCategory"></param>
        /// <param name="ownerId">Идентификатор владельца Like-объекта: id пользователя, id сообщества (со знаком минус) или id приложения.</param>
        /// <param name="likeObjectId">Идентификатор Like-объекта.</param>
        /// <param name="likeObjectType">Тип Like-объекта.</param>
        /// <param name="offset">Смещение, относительно начала списка, для выборки определенного подмножества.</param>
        /// <param name="count">Количество возвращаемых идентификаторов пользователей. Максимальное значение: 1000.</param>
        /// <returns></returns>
        private static VkCollection<long> LikesGetList(LikesCategory likesCategory, long ownerId, long likeObjectId, LikeObjectType likeObjectType, int offset, int count)
        {
            if (likesCategory == null) return null;

            byte b = 0;
            do
            {
                try
                {
                    return likesCategory.GetList(new LikesGetListParams
                                                 {
                                                     OwnerId = ownerId,
                                                     ItemId = likeObjectId,
                                                     Type = likeObjectType,
                                                     Offset = offset < 0 ? 0 : (uint) offset,
                                                     Count = count < 0 ? 0 : (uint) count
                                                 });
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}" +
                                      $"\n{exception}" +
                                      $"\n   owner ID:         {ownerId}" +
                                      $"\n   like object ID:   {likeObjectId}" +
                                      $"\n   like object type: {likeObjectType}" +
                                      $"\n   offset:           {offset}" +
                                      $"\n   count:            {count}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }

        /// <summary>
        /// Возвращает список идентификаторов пользователей, которые выбрали определенные варианты ответа в опросе.
        /// </summary>
        /// <param name="postOrCommentId">Идентификатор записи.</param>
        /// <param name="pollsCategory"></param>
        /// <param name="ownerId">Идентификатор пользователя или сообщества, которому принадлежит опрос.</param>
        /// <param name="pollId">Идентификатор опроса.</param>
        /// <param name="answerIds">Идентификаторы вариантов ответа.</param>
        /// <param name="offset">
        /// Смещение относительно начала списка, для выборки определенного подмножества.
        /// Если параметр не задан, то считается, что он равен 0.
        /// </param>
        /// <param name="count">
        /// Количество возвращаемых идентификаторов пользователей.
        /// Если параметр не задан, то считается, что он равен 100, если не задан параметр friends_only, в противном случае 10.
        /// Максимальное значение параметра 1000, если не задан параметр friends_only, в противном случае 100.
        /// </param>
        /// <returns></returns>
        private static VkCollection<PollAnswerVoters> PollsGetVoters(long postOrCommentId,
                                                                     PollsCategory pollsCategory,
                                                                     long ownerId,
                                                                     long pollId,
                                                                     List<long> answerIds,
                                                                     long offset,
                                                                     int count)
        {
            if (pollsCategory == null || answerIds == null || answerIds.Count <= 0) return null;

            byte b = 0;
            do
            {
                try
                {
                    return pollsCategory.GetVoters(new PollsGetVotersParams
                                                   {
                                                       OwnerId = ownerId,
                                                       PollId = pollId,
                                                       AnswersIds = answerIds,
                                                       Offset = offset < 0 ? 0 : offset,
                                                       Count = count < 0 ? 0 : count
                                                   });
                }
                catch (VkApiException exception) when (exception.ErrorCode == 250) // Access to poll denied
                {
                    Console.WriteLine($"\n{DateTime.Now}" +
                                      $"\n{exception}" +
                                      $"\n   post or comment ID: {postOrCommentId}" +
                                      $"\n   owner ID:           {ownerId}" +
                                      $"\n   poll ID:            {pollId}" +
                                      $"\n   answer IDs:         {string.Join(", ", answerIds)}" +
                                      $"\n   offset:             {offset}" +
                                      $"\n   count:              {count}");
                    break;
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}" +
                                      $"\n{exception}" +
                                      $"\n   post or comment ID: {postOrCommentId}" +
                                      $"\n   owner ID:           {ownerId}" +
                                      $"\n   poll ID:            {pollId}" +
                                      $"\n   answer IDs:         {string.Join(", ", answerIds)}" +
                                      $"\n   offset:             {offset}" +
                                      $"\n   count:              {count}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }

        /// <summary>
        /// Возвращает расширенную информацию о пользователях.
        /// </summary>
        /// <param name="usersCategory"></param>
        /// <param name="userIds">Список идентификаторов пользователей.</param>
        /// <returns></returns>
        private static ReadOnlyCollection<User> UsersGet(UsersCategory usersCategory, HashSet<long> userIds)
        {
            if (usersCategory == null) return null;

            byte b = 0;
            do
            {
                try
                {
                    return usersCategory.Get(userIds, ProfileFields.City | ProfileFields.BirthDate);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}\n{exception}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }

        /// <summary>
        /// Возвращает список записей со стены пользователя или сообщества.
        /// </summary>
        /// <param name="wallCategory"></param>
        /// <param name="ownerId">
        /// Идентификатор пользователя или сообщества, со стены которого необходимо получить записи (по умолчанию - текущий пользователь).
        /// Идентификатор сообщества необходимо указывать со знаком минус.
        /// </param>
        /// <param name="offset">Смещение, относительно начала списка, для выборки определенного подмножества.</param>
        /// <param name="count">Количество возвращаемых записей. Максимальное значение: 100.</param>
        /// <returns></returns>
        private static WallGetObject WallGet(WallCategory wallCategory, long ownerId, int offset, int count)
        {
            if (wallCategory == null) return null;

            byte b = 0;
            do
            {
                try
                {
                    return wallCategory.Get(new WallGetParams {OwnerId = ownerId, Offset = offset < 0 ? 0 : (ulong) offset, Count = count < 0 ? 0 : (ulong) count});
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}" +
                                      $"\n{exception}" +
                                      $"\n   owner ID: {ownerId}" +
                                      $"\n   offset:   {offset}" +
                                      $"\n   count:    {count}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }

        /// <summary>
        /// Возвращает список комментариев к записи на стене.
        /// </summary>
        /// <param name="wallCategory"></param>
        /// <param name="ownerId">
        /// Идентификатор владельца страницы (пользователя или сообщества).
        /// Идентификатор сообщества необходимо указывать со знаком минус.</param>
        /// <param name="postId">Идентификатор записи на стене.</param>
        /// <param name="offset">Смещение, относительно начала списка, для выборки определенного подмножества.</param>
        /// <param name="count">Количество возвращаемых комментариев. Максимальное значение: 100.</param>
        /// <returns></returns>
        private static VkCollection<Comment> WallGetComments(WallCategory wallCategory, long ownerId, long postId, int offset, int count)
        {
            if (wallCategory == null) return null;

            byte b = 0;
            do
            {
                try
                {
                    return wallCategory.GetComments(new WallGetCommentsParams
                                                    {
                                                        OwnerId = ownerId,
                                                        PostId = postId,
                                                        Offset = offset,
                                                        Count = count < 0 ? 0 : count,
                                                        NeedLikes = true
                                                    });
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"\n{DateTime.Now}" +
                                      $"\n{exception}" +
                                      $"\n   owner ID: {ownerId}" +
                                      $"\n   post ID:  {postId}" +
                                      $"\n   offset:   {offset}" +
                                      $"\n   count:    {count}");
                    Task.Delay(MillisecondsDelay).Wait();
                }
                b++;
            } while (b < AttemptCount);
            return null;
        }
    }
}

{'content_hash': '9eb14a8d0f6650751177fdea2e6ce333', 'timestamp': '', 'source': 'github', 'line_count': 839, 'max_line_length': 170, 'avg_line_length': 43.80333730631705, 'alnum_prop': 0.4303012162934342, 'repo_name': 'sergey-redskin/Anticutan', 'id': '683e0b1cfb15d83cee5fb5c0ab16f5b683dd1214', 'size': '38986', 'binary': False, 'copies': '1', 'ref': 'refs/heads/master', 'path': 'Anticutan/Anticutan.Data/VkApiWrapper.cs', 'mode': '33188', 'license': 'mit', 'language': [{'name': 'C#', 'bytes': '139279'}]}


// Copyright (c)  Zhirnov Andrey. For more information see 'LICENSE.txt'

#pragma once

#include "Core/STL/Math/Mathematics.h"
#include "Core/STL/Math/Vec.h"
#include "TR11G11B10F.h"
#include "TRGB9_E5.h"
#include "Half.h"

namespace GX_STL
{
namespace GXMath
{

	namespace _color_hidden_
	{
		struct EColorFormatDescriptor { enum type
		{
			UNKNOWN		= 0,
			SIGNED		= 1 << 0,
			UNSIGNED	= 1 << 1,
			INTEGER		= 1 << 2,
			FLOAT		= 1 << 3,
			NORMALIZED	= 1 << 4,

			// default //
			SINT		= SIGNED | INTEGER,
			UINT		= UNSIGNED | INTEGER,
			SFLOAT		= SIGNED | FLOAT,
			UFLOAT		= UNSIGNED | FLOAT,
		};};

#	ifdef GX_COLOR_FORMAT_HIGH_PRECISION
		typedef ilong4	IntFormat;
		typedef double4	FloatFormat;
#	else
		typedef int4	IntFormat;
		typedef float4	FloatFormat;
#	endif

		//
		// Max int color format components size in bits
		//
		struct IntColorFormatInfo
		{
		// variables
		private:
			IntFormat	sizeInBits;
			bool		isSigned;

		// methods
		private:
			IntColorFormatInfo () : sizeInBits{0}, isSigned{false}
			{}

			template <typename ColorType>
			IntColorFormatInfo (uint sizeR, uint sizeG, uint sizeB, uint sizeA, const ColorType &) :
				sizeInBits( sizeR, sizeG, sizeB, sizeA ),
				isSigned( (ColorType::format & EColorFormatDescriptor::SIGNED) != 0 )
			{
				STATIC_ASSERT( (ColorType::format & EColorFormatDescriptor::INTEGER) != 0,
								"color format must be integer" );

				ASSERT( (sizeR + sizeG + sizeB + sizeA) == CompileTime::SizeOf<ColorType>::bits );
			}

		public:
			template <uint sizeR, uint sizeG, uint sizeB, uint sizeA, typename ColorType>
			ND_ static IntColorFormatInfo  PackedType (const ColorType &color)
			{
				STATIC_ASSERT( (sizeR + sizeG + sizeB + sizeA) == CompileTime::SizeOf<ColorType>::bits );
				return IntColorFormatInfo( sizeR, sizeG, sizeB, sizeA, color );
			}

			template <typename ValueType, uint ChannelsCount, typename ColorType>
			ND_ static IntColorFormatInfo  SimpleType (const ColorType &color)
			{
				const uint channel_size = CompileTime::SizeOf<ValueType>::bits;

				STATIC_ASSERT( (channel_size * ChannelsCount) == CompileTime::SizeOf<ColorType>::bits );
				STATIC_ASSERT( ChannelsCount > 0 and ChannelsCount <= 4 );

				return IntColorFormatInfo( ChannelsCount > 0 ? channel_size : 0,
									ChannelsCount > 1 ? channel_size : 0,
									ChannelsCount > 2 ? channel_size : 0,
									ChannelsCount > 3 ? channel_size : 0,
									color );
			}

			template <uint R, uint G, uint B, uint A>
			ND_ IntColorFormatInfo  GetSwizzledFormat () const
			{
				IntColorFormatInfo	res;
				res.sizeInBits = IntFormat( this->sizeInBits[R&3], this->sizeInBits[G&3],
											this->sizeInBits[B&3], this->sizeInBits[A&3] );
				res.isSigned = this->isSigned;
				return res;
			}

			ND_ IntFormat  MaxValue () const
			{
				return ToMask< IntFormat::Value_t >( Max( sizeInBits - int(isSigned), IntFormat() ).To<Vec<BitsU,4>>() );
			}

			ND_ FloatFormat  MaxValueF () const
			{
				return this->MaxValue().To<FloatFormat>();
			}

			ND_ IntFormat  MinValue () const
			{
				return isSigned ? (-MaxValue()-1) : IntFormat(0);
			}

			ND_ IntFormat  GetShiftTo (const IntColorFormatInfo &fmt) const
			{
				return fmt.sizeInBits - sizeInBits;
			}

			ND_ IntFormat  GetShiftFrom (const IntColorFormatInfo &fmt) const
			{
				return -GetShiftTo( fmt );
			}

			ND_ IntFormat  Clamp (const IntFormat &value) const
			{
				typedef Vec< CompileTime::NearInt::FromType< IntFormat::Value_t >, 4 >	sign_t;
				typedef Vec< CompileTime::NearUInt::FromType< IntFormat::Value_t >, 4 >	unsign_t;

				return isSigned ?
						GXMath::Clamp( value, MinValue(), MaxValue() ) :
						GXMath::Clamp( value.To<unsign_t>(), MinValue().To<unsign_t>(), MaxValue().To<unsign_t>() ).To<sign_t>();
			}
		};

		//
		// Float format
		//
		struct FloatColorFormatInfo
		{
		// variables
		private:
			FloatFormat	maxValue,
						minValue;
			bool		isSigned;

		// methods
		private:
			FloatColorFormatInfo (const FloatFormat &maxValue, const FloatFormat &minValue, bool isSigned) :
				maxValue(maxValue), minValue(minValue), isSigned(isSigned)
			{}

		public:
			template <typename ValueType>
			ND_ static FloatColorFormatInfo  SimpleType ()
			{
				const ValueType	min_value = GXTypes::MinValue<ValueType>();
				const ValueType	max_value = GXTypes::MaxValue<ValueType>();

				return FloatColorFormatInfo( FloatFormat{max_value}, FloatFormat{min_value}, true );
			}

			ND_ static FloatColorFormatInfo  PackedType (const FloatFormat &maxValue)
			{
				return FloatColorFormatInfo( maxValue, FloatFormat(0.0f), false );
			}

			template <uint R, uint G, uint B, uint A>
			ND_ FloatColorFormatInfo  GetSwizzledFormat () const
			{
				FloatColorFormatInfo	res( FloatFormat( this->maxValue[R&3], this->maxValue[G&3],
														  this->maxValue[B&3], this->maxValue[A&3] ),
											 FloatFormat( this->minValue[R&3], this->minValue[G&3],
														  this->minValue[B&3], this->minValue[A&3] ),
											 this->isSigned );
				return res;
			}

			ND_ FloatFormat  MaxValue () const
			{
				return maxValue;
			}

			ND_ FloatFormat  MinValue () const
			{
				return isSigned ? -maxValue : FloatFormat(0.0f);
			}

			ND_ FloatFormat  Clamp (const FloatFormat &value) const
			{
				FloatFormat		ret;
				FOR( i, ret )	ret[i] = GXMath::Clamp( value[i], MinValue()[i], MaxValue()[i] );
				return ret;
			}
		};

		//
		// Color Format Converter
		//
		struct ColorFormatConverter
		{
			template <typename ColorType>
			static constexpr bool	IsInteger		= (ColorType::format & EColorFormatDescriptor::INTEGER) != 0;

			template <typename ColorType>
			static constexpr bool	IsFloat			= (ColorType::format & EColorFormatDescriptor::FLOAT) != 0;

			template <typename ColorType>
			static constexpr bool	IsNormalized	= (ColorType::format & EColorFormatDescriptor::NORMALIZED) != 0;

			template <typename ColorType>
			static constexpr bool	IsUnnormalized	= (ColorType::format & EColorFormatDescriptor::NORMALIZED) == 0;

			template <typename ColorType>
			static void MustBeInteger ()
			{
				STATIC_ASSERT( IsInteger<ColorType>, "color format must be integer" );
			}

			template <typename ColorType>
			static void MustBeFloat ()
			{
				STATIC_ASSERT( IsFloat<ColorType>, "color format must be float" );
			}

			template <typename ColorType>
			static void MustBeNormalized ()
			{
				STATIC_ASSERT( IsNormalized<ColorType>, "color format must be normalized" );
			}

			template <typename ColorType>
			static void MustBeUnnormalized ()
			{
				STATIC_ASSERT( IsUnnormalized<ColorType>, "color format must be not normalized" );
			}

			// normalized int to normalized int
			template <typename SrcColorType, typename DstColorType>
			static void NormIntToNormInt (DstColorType &dst, const SrcColorType &src)
			{
				typedef IntFormat::Value_t	Int_t;

				MustBeInteger< SrcColorType >();
				MustBeInteger< DstColorType >();
				MustBeNormalized< DstColorType >();

				IntColorFormatInfo const	dfmt(dst);
				IntColorFormatInfo const	sfmt(src);

				IntFormat const		shift = sfmt.GetShiftTo( dfmt );
				IntFormat const		scolor(src);
				IntFormat			dcolor;
				Int_t const			one = Int_t(1);

				FOR( i, dcolor )
				{
					Int_t const	half_val = ( one << Max( Abs(shift[i])-1, 0 ) ) - 1;

					dcolor[i] = shift[i] >= 0 ?
								(scolor[i] << +shift[i]) + half_val :
								(scolor[i] + half_val) >> -shift[i];
				}

				dst = dfmt.Clamp( dcolor );
			}

			// int to normalized int

			// normalized int to int
			/*template <typename SrcColorType, typename DstColorType>
			static void NormIntToInt (DstColorType &dst, const SrcColorType &src)
			{
				MustBeNormalized< SrcColorType >();
				MustBeInteger< SrcColorType >();
				MustBeInteger< DstColorType >();

				IntColorFormatInfo const	dfmt(dst);
				IntColorFormatInfo const	sfmt(src);

				IntFormat const		scolor(src);
				IntFormat			dcolor = Round< IntFormat::Value_t >( scolor.To<FloatFormat>() / sfmt.MaxValueF() );

				dst = dfmt.Clamp( dcolor );
			}*/

			// int to int (not normalized)
			template <typename SrcColorType, typename DstColorType>
			static void IntToInt (DstColorType &dst, const SrcColorType &src)
			{
				MustBeInteger< SrcColorType >();
				MustBeInteger< DstColorType >();
				MustBeUnnormalized< DstColorType >();

				IntColorFormatInfo const	dfmt(dst);
				IntFormat const				scolor(src);

				dst = dfmt.Clamp( scolor );
			}

			// normalized int to normalized float
			template <typename SrcColorType, typename DstColorType>
			static void NormIntToNormFloat (DstColorType &dst, const SrcColorType &src)
			{
				MustBeNormalized< SrcColorType >();
				MustBeInteger< SrcColorType >();
				MustBeFloat< DstColorType >();

				IntColorFormatInfo const	sfmt(src);
				FloatColorFormatInfo const	dfmt(dst);
				IntFormat   const			scolor(src);
				FloatFormat const			dcolor = scolor.template To<FloatFormat>() / sfmt.MaxValueF();

				dst = dfmt.Clamp( dcolor );
			}

			// int to normalized float
			template <typename SrcColorType, typename DstColorType>
			static void IntToNormFloat (DstColorType &dst, const SrcColorType &src)
			{
				MustBeUnnormalized< SrcColorType >();
				MustBeInteger< SrcColorType >();
				MustBeFloat< DstColorType >();

				IntColorFormatInfo const	sfmt(src);
				FloatColorFormatInfo const	dfmt(dst);
				IntFormat   const			scolor(src);
				FloatFormat const			dcolor = scolor.template To<FloatFormat>();

				dst = dfmt.Clamp( dcolor );
			}

			// int to float (not normalized)
			template <typename SrcColorType, typename DstColorType>
			static void IntToFloat (DstColorType &dst, const SrcColorType &src)
			{
				MustBeInteger< SrcColorType >();
				MustBeFloat< DstColorType >();

				IntColorFormatInfo const	sfmt(src);
				FloatColorFormatInfo const	dfmt(dst);
				IntFormat   const			scolor(src);
				FloatFormat const			dcolor = scolor.template To<FloatFormat>();

				dst = dfmt.Clamp( dcolor );
			}

			// float to normalized int
			template <typename SrcColorType, typename DstColorType>
			static void FloatToNormInt (DstColorType &dst, const SrcColorType &src)
			{
				MustBeFloat< SrcColorType >();
				MustBeInteger< DstColorType >();
				MustBeNormalized< DstColorType >();

				FloatColorFormatInfo const	sfmt(src);
				IntColorFormatInfo const	dfmt(dst);
				FloatFormat const			scolor(src);
				IntFormat   const			dcolor = RoundToInt( scolor );

				dst = dfmt.Clamp( dcolor );
			}

			// normalized float to normalized int
			template <typename SrcColorType, typename DstColorType>
			static void NormFloatToNormInt (DstColorType &dst, const SrcColorType &src)
			{
				MustBeFloat< SrcColorType >();
				MustBeInteger< DstColorType >();
				MustBeNormalized< DstColorType >();

				FloatColorFormatInfo const	sfmt(src);
				IntColorFormatInfo const	dfmt(dst);
				FloatFormat const			scolor(src);
				IntFormat   const			dcolor = RoundToInt( scolor * dfmt.MaxValueF() );

				dst = dfmt.Clamp( dcolor );
			}

			// float to int (not normalized)
			template <typename SrcColorType, typename DstColorType>
			static void FloatToInt (DstColorType &dst, const SrcColorType &src)
			{
				MustBeFloat< SrcColorType >();
				MustBeInteger< DstColorType >();

				FloatColorFormatInfo const	sfmt(src);
				IntColorFormatInfo const	dfmt(dst);
				FloatFormat const			scolor(src);
				IntFormat   const			dcolor = RoundToInt( scolor );

				dst = dfmt.Clamp( dcolor );
			}

			// float to float (normalized or not normalized)
			template <typename SrcColorType, typename DstColorType>
			static void FloatToFloat (DstColorType &dst, const SrcColorType &src)
			{
				MustBeFloat< SrcColorType >();
				MustBeFloat< DstColorType >();

				FloatColorFormatInfo const	dfmt(dst);

				dst = dfmt.Clamp( FloatFormat(src) );
			}

			template <typename SrcColorType, typename DstColorType>
			static void Convert (DstColorType &dst, const SrcColorType &src);
		};

		template <typename Src, typename Dst, bool SrcInt, bool DstInt, bool SrcNorm, bool DstNorm>
		struct ConverterSwitch
		{
			/*static void Convert (Dst &dst, const Src &src)
			{
				DESKTOP_ONLY( STATIC_WARNING( "not implementation for this formats!" ) );
			}*/
		};

#		define CONVERTER_SWITCH( _srcInt_, _dstInt_, _srcNorm_, _dstNorm_, _func_ ) \
			template <typename Src, typename Dst> \
			struct ConverterSwitch < Src, Dst, _srcInt_, _dstInt_, _srcNorm_, _dstNorm_ > \
			{ \
				static void Convert (Dst &dst, const Src &src) \
				{ \
					ColorFormatConverter::_func_( dst, src ); \
				} \
			}

		//				  srcInt, dstInt, srcNorm, dstNorm,   func
		CONVERTER_SWITCH( false,  false,  false,   false,     FloatToFloat );
		CONVERTER_SWITCH( false,  false,  false,   true,      FloatToFloat );
		CONVERTER_SWITCH( false,  false,  true,    false,     FloatToFloat );
		CONVERTER_SWITCH( false,  false,  true,    true,      FloatToFloat );

		CONVERTER_SWITCH( false,  true,   false,   false,     FloatToInt );
		CONVERTER_SWITCH( false,  true,   false,   true,      NormFloatToNormInt );
		CONVERTER_SWITCH( false,  true,   true,    false,     FloatToInt );
		CONVERTER_SWITCH( false,  true,   true,    true,      NormFloatToNormInt );

		CONVERTER_SWITCH( true,   false,  false,   false,     IntToFloat );
		CONVERTER_SWITCH( true,   false,  false,   true,      IntToNormFloat );
		CONVERTER_SWITCH( true,   false,  true,    false,     NormIntToNormFloat );
		CONVERTER_SWITCH( true,   false,  true,    true,      NormIntToNormFloat );

		CONVERTER_SWITCH( true,   true,   false,   false,     IntToInt );
		CONVERTER_SWITCH( true,   true,   false,   true,      NormIntToNormInt );
		CONVERTER_SWITCH( true,   true,   true,    false,     IntToInt );
		CONVERTER_SWITCH( true,   true,   true,    true,      NormIntToNormInt );

#		undef CONVERTER_SWITCH

		template <typename SrcColorType, typename DstColorType>
		inline void ColorFormatConverter::Convert (DstColorType &dst, const SrcColorType &src)
		{
			ConverterSwitch< SrcColorType,
							 DstColorType,
							 (SrcColorType::format & EColorFormatDescriptor::INTEGER) != 0,
							 (DstColorType::format & EColorFormatDescriptor::INTEGER) != 0,
							 (SrcColorType::format & EColorFormatDescriptor::NORMALIZED) != 0,
							 (DstColorType::format & EColorFormatDescriptor::NORMALIZED) != 0 >
				::Convert( dst, src );
		}

# ifdef COMPILER_MSVC
#	pragma warning (push)
#	pragma warning (disable: 4244)		// convert to smallest type
# endif

		//
		// Base Color Type
		//
		template <typename T, bool Normalized = false>
		struct BaseColor : public CompileTime::CopyQualifiers< T >
		{
			static const bool	_is_float		= CompileTime::IsFloat<T>;
			static const bool	_is_integer		= CompileTime::IsInteger<T> or not _is_float;
			static const bool	_is_signed		= CompileTime::IsSigned<T>;
			static const bool	_is_unsigned	= CompileTime::IsUnsigned<T> or not _is_signed;
			static const bool	_is_normalized	= Normalized;

			static const uint	format	=
									(_is_integer ? EColorFormatDescriptor::INTEGER :  EColorFormatDescriptor::FLOAT) |
									(_is_unsigned ? EColorFormatDescriptor::UNSIGNED : EColorFormatDescriptor::SIGNED) |
									(_is_normalized ? EColorFormatDescriptor::NORMALIZED : 0 );

			STATIC_ASSERT( _is_signed != _is_unsigned );
		};

	//-----------------------------------------------
	// Integer Formats

		//
		// Red or Alpha
		//
		template <typename T, bool Normalized = false>
		struct RedI : BaseColor<T, Normalized>
		{
			using Result_t = IntFormat;

			T	r;

			RedI () : r(0) {}
			RedI (T R) : r(R) {}
			RedI (const IntFormat &c) : r(c[0]) {}

			operator IntFormat () const						{ return IntFormat( r, 0, 0, 0 ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::SimpleType<T,1>( *this ); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RG
		//
		template <typename T, bool Normalized = false>
		struct RGi : BaseColor<T, Normalized>
		{
			using Result_t = IntFormat;

			T	r, g;

			RGi () : r(0), g(0) {}
			RGi (T R, T G) : r(R), g(G) {}
			RGi (const IntFormat &c) : r(c[0]), g(c[1]) {}

			operator IntFormat () const						{ return IntFormat( r, g, 0, 0 ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::SimpleType<T,2>( *this ); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGB
		//
		template <typename T, bool Normalized = false>
		struct RGBi : BaseColor<T, Normalized>
		{
			using Result_t = IntFormat;

			T	r, g, b;

			RGBi () : r(0), g(0), b(0) {}
			RGBi (T R, T G, T B) : r(R), g(G), b(B) {}
			RGBi (const IntFormat &c) : r(c[0]), g(c[1]), b(c[2]) {}

			operator IntFormat () const						{ return IntFormat( r, g, b, 0 ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::SimpleType<T,3>( *this ); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGBA
		//
		template <typename T, bool Normalized = false>
		struct RGBAi : BaseColor<T, Normalized>
		{
			using Result_t = IntFormat;

			T	r, g, b, a;

			RGBAi () : r(0), g(0), b(0), a(0) {}
			RGBAi (T R, T G, T B, T A) : r(R), g(G), b(B), a(A) {}
			RGBAi (const IntFormat &c) : r(c[0]), g(c[1]), b(c[2]), a(c[3]) {}

			operator IntFormat () const						{ return IntFormat( r, g, b, a ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::SimpleType<T,4>( *this ); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGBA 16-bit
		//
		template <bool Normalized = false>
		struct RGBA4u
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				ushort	a : 4,
						b : 4,
						g : 4,
						r : 4;
			};
			union {
				Bits	bits;
				ushort	data;
			};

			RGBA4u () : data(0)							{}
			RGBA4u (ubyte R, ubyte G, ubyte B, ubyte A)	{ bits.r = R;  bits.g = G;  bits.b = B;  bits.a = A; }
			RGBA4u (const IntFormat &c)					{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2];  bits.a = c[3]; }

			operator IntFormat () const						{ return IntFormat( bits.r, bits.g, bits.b, bits.a ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::PackedType< 4, 4, 4, 4 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGBA 16-bit Reverse
		//
		template <bool Normalized = false>
		struct RGBA4u_Rev
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				ushort	r : 4,
						g : 4,
						b : 4,
						a : 4;
			};
			union {
				Bits	bits;
				ushort	data;
			};

			RGBA4u_Rev () : data(0)							{}
			RGBA4u_Rev (ubyte R, ubyte G, ubyte B, ubyte A)	{ bits.r = R;  bits.g = G;  bits.b = B;  bits.a = A; }
			RGBA4u_Rev (const IntFormat &c)					{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2];  bits.a = c[3]; }

			operator IntFormat () const						{ return IntFormat( bits.r, bits.g, bits.b, bits.a ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::PackedType< 4, 4, 4, 4 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGBA 16-bit
		//
		template <bool Normalized = false>
		struct RGB5_A1u
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				ushort	a : 1,
						b : 5,
						g : 5,
						r : 5;
			};
			union {
				Bits	bits;
				ushort	data;
			};

			RGB5_A1u () : data(0) {}
			RGB5_A1u (ubyte R, ubyte G, ubyte B, bool A)	{ bits.r = R;  bits.g = G;  bits.b = B;  bits.a = A; }
			RGB5_A1u (const IntFormat &c)					{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2];  bits.a = c[3]; }

			operator IntFormat () const						{ return IntFormat( bits.r, bits.g, bits.b, bits.a ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::PackedType< 5, 5, 5, 1 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGBA 16-bit Reverse
		//
		template <bool Normalized = false>
		struct RGB5_A1u_Rev
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				ushort	r : 5,
						g : 5,
						b : 5,
						a : 1;
			};
			union {
				Bits	bits;
				ushort	data;
			};

			RGB5_A1u_Rev () : data(0) {}
			RGB5_A1u_Rev (ubyte R, ubyte G, ubyte B, bool A)	{ bits.r = R;  bits.g = G;  bits.b = B;  bits.a = A; }
			RGB5_A1u_Rev (const IntFormat &c)					{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2];  bits.a = c[3]; }

			operator IntFormat () const							{ return IntFormat( bits.r, bits.g, bits.b, bits.a ); }
			explicit operator IntColorFormatInfo () const		{ return IntColorFormatInfo::PackedType< 5, 5, 5, 1 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGB 16-bit
		//
		template <bool Normalized = false>
		struct R5_G6_B5u
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				ushort	b : 5,
						g : 6,
						r : 5;
			};
			union {
				Bits	bits;
				ushort	data;
			};

			R5_G6_B5u () : data(0) {}
			R5_G6_B5u (ubyte R, ubyte G, ubyte B)	{ bits.r = R;  bits.g = G;  bits.b = B; }
			R5_G6_B5u (const IntFormat &c)			{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2]; }

			operator IntFormat () const						{ return IntFormat( bits.r, bits.g, bits.b, 0 ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::PackedType< 5, 6, 5, 0 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGB 16-bit Reverse
		//
		template <bool Normalized = false>
		struct R5_G6_B5u_Rev
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				ushort	r : 5,
						g : 6,
						b : 5;
			};
			union {
				Bits	bits;
				ushort	data;
			};

			R5_G6_B5u_Rev () : data(0) {}
			R5_G6_B5u_Rev (ubyte R, ubyte G, ubyte B)	{ bits.r = R;  bits.g = G;  bits.b = B; }
			R5_G6_B5u_Rev (const IntFormat &c)			{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2]; }

			operator IntFormat () const						{ return IntFormat( bits.r, bits.g, bits.b, 0 ); }
			explicit operator IntColorFormatInfo () const	{ return IntColorFormatInfo::PackedType< 5, 6, 5, 0 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGBA 32-bit
		//
		template <bool Normalized = false>
		struct RGB10_A2u
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				uint	a : 2,
						b : 10,
						g : 10,
						r : 10;
			};
			union {
				Bits	bits;
				uint	data;
			};

			RGB10_A2u () : data(0) {}
			RGB10_A2u (ushort R, ushort G, ushort B, ubyte A)	{ bits.r = R;  bits.g = G;  bits.b = B;  bits.a = A; }
			RGB10_A2u (const IntFormat &c)						{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2];  bits.a = c[3]; }

			operator IntFormat () const							{ return IntFormat( bits.r, bits.g, bits.b, bits.a ); }
			explicit operator IntColorFormatInfo () const		{ return IntColorFormatInfo::PackedType< 10, 10, 10, 2 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

		//
		// RGBA 32-bit Reverse
		//
		template <bool Normalized = false>
		struct RGB10_A2u_Rev
		{
			using Result_t = IntFormat;

			enum { format = EColorFormatDescriptor::UINT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			struct Bits {
				uint	r : 10,
						g : 10,
						b : 10,
						a : 2;
			};
			union {
				Bits	bits;
				uint	data;
			};

			RGB10_A2u_Rev () : data(0) {}
			RGB10_A2u_Rev (ushort R, ushort G, ushort B, ubyte A)	{ bits.r = R;  bits.g = G;  bits.b = B;  bits.a = A; }
			RGB10_A2u_Rev (const IntFormat &c)						{ bits.r = c[0];  bits.g = c[1];  bits.b = c[2];  bits.a = c[3]; }

			operator IntFormat () const								{ return IntFormat( bits.r, bits.g, bits.b, bits.a ); }
			explicit operator IntColorFormatInfo () const			{ return IntColorFormatInfo::PackedType< 10, 10, 10, 2 >(*this); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( IntFormat(*this) == IntFormat(right) );
			}
		};

	//-----------------------------------------------
	// Float Formats

		//
		// RGB 32-bit
		//
		template <bool Normalized = false>
		struct R11_G11_B10f
		{
			using Result_t = FloatFormat;

			enum { format = EColorFormatDescriptor::UFLOAT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			typedef r11g11b10f_t::Vec3_t	Vec3_t;

			r11g11b10f_t	data;

			R11_G11_B10f () {}
			R11_G11_B10f (float R, float G, float B) : data{ R, G, B } {}
			R11_G11_B10f (const FloatFormat &c) : data{ c }		{}

			operator FloatFormat () const						{ return Vec3_t(data).To<FloatFormat>(); }
			explicit operator FloatColorFormatInfo () const		{ return FloatColorFormatInfo::PackedType( FloatFormat(*this) ); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( FloatFormat(*this) == FloatFormat(right) );
			}
		};

		//
		// RGB9 E5 32-bit
		//
		template <bool Normalized = false>
		struct RGB9_E5f_Rev
		{
			using Result_t = FloatFormat;

			enum { format = EColorFormatDescriptor::UFLOAT | (Normalized ? EColorFormatDescriptor::NORMALIZED : 0) };

			typedef rgb9_e5_t::Vec3_t	Vec3_t;

			rgb9_e5_t	data;

			RGB9_E5f_Rev () {}
			RGB9_E5f_Rev (float R, float G, float B)	{ data.Set( R, G, B ); }
			RGB9_E5f_Rev (const FloatFormat &c)			{ data.Set( c[0], c[1], c[2] ); }

			operator FloatFormat () const						{ return Vec3_t(data).To<FloatFormat>(); }
			explicit operator FloatColorFormatInfo () const		{ return FloatColorFormatInfo::PackedType( FloatFormat(*this) ); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( FloatFormat(*this) == FloatFormat(right) );
			}
		};

		// TODO: RGB9_E5f

		//
		// Red
		//
		template <typename T, bool Normalized = false>
		struct RedF : BaseColor<T, Normalized>
		{
			using Result_t = FloatFormat;

			T	r;

			RedF () : r(0) {}
			RedF (T R) : r(R) {}
			RedF (const FloatFormat &c)				{ r = c[0]; }

			operator FloatFormat () const					{ return FloatFormat( r, 0.0f, 0.0f, 0.0f ); }
			explicit operator FloatColorFormatInfo () const	{ return FloatColorFormatInfo::SimpleType<T>(); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( FloatFormat(*this) == FloatFormat(right) );
			}
		};

		//
		// RG
		//
		template <typename T, bool Normalized = false>
		struct RGf : BaseColor<T, Normalized>
		{
			using Result_t = FloatFormat;

			T	r, g;

			RGf () : r(0), g(0)						{}
			RGf (T R, T G) : r(R), g(G)				{}
			RGf (const FloatFormat &c)				{ r = c[0];  g = c[1]; }

			operator FloatFormat () const					{ return FloatFormat( r, g, 0.0f, 0.0f ); }
			explicit operator FloatColorFormatInfo () const	{ return FloatColorFormatInfo::SimpleType<T>(); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( FloatFormat(*this) == FloatFormat(right) );
			}
		};

		//
		// RGB
		//
		template <typename T, bool Normalized = false>
		struct RGBf : BaseColor<T, Normalized>
		{
			using Result_t = FloatFormat;

			T	r, g, b;

			RGBf () : r(0), g(0), b(0)				{}
			RGBf (T R, T G, T B) : r(R), g(G), b(B) {}
			RGBf (const FloatFormat &c)				{ r = c[0];  g = c[1];  b = c[2]; }

			operator FloatFormat () const					{ return FloatFormat( r, g, b, 0.0f ); }
			explicit operator FloatColorFormatInfo () const	{ return FloatColorFormatInfo::SimpleType<T>(); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( FloatFormat(*this) == FloatFormat(right) );
			}
		};

		//
		// RGBA
		//
		template <typename T, bool Normalized = false>
		struct RGBAf : BaseColor<T, Normalized>
		{
			using Result_t = FloatFormat;

			T	r, g, b, a;

			RGBAf () : r(0), g(0), b(0), a(0) {}
			RGBAf (T R, T G, T B, T A) : r(R), g(G), b(B), a(A) {}
			RGBAf (const FloatFormat &c)			{ r = c[0];  g = c[1];  b = c[2];  a = c[3]; }

			operator FloatFormat () const					{ return FloatFormat( r, g, b, a ); }
			explicit operator FloatColorFormatInfo () const	{ return FloatColorFormatInfo::SimpleType<T>(); }

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( FloatFormat(*this) == FloatFormat(right) );
			}
		};

# ifdef COMPILER_MSVC
#	pragma warning (pop)
# endif

	}	// _color_hidden_

	namespace ColorFormat
	{
		// unnormalized formats
		typedef _color_hidden_::RedI<ubyte>		R8u;
		typedef _color_hidden_::RedI<ushort>	R16u;
		typedef _color_hidden_::RedI<uint>		R32u;
		typedef _color_hidden_::RedI<ulong>		R64u;
		typedef _color_hidden_::RedI<byte>		R8i;
		typedef _color_hidden_::RedI<short>		R16i;
		typedef _color_hidden_::RedI<int>		R32i;
		typedef _color_hidden_::RedI<ilong>		R64i;

		typedef _color_hidden_::RGi<ubyte>		RG8u;
		typedef _color_hidden_::RGi<ushort>		RG16u;
		typedef _color_hidden_::RGi<uint>		RG32u;
		typedef _color_hidden_::RGi<ulong>		RG64u;
		typedef _color_hidden_::RGi<byte>		RG8i;
		typedef _color_hidden_::RGi<short>		RG16i;
		typedef _color_hidden_::RGi<int>		RG32i;
		typedef _color_hidden_::RGi<ilong>		RG64i;

		typedef _color_hidden_::RGBi<ubyte>		RGB8u;
		typedef _color_hidden_::RGBi<ushort>	RGB16u;
		typedef _color_hidden_::RGBi<uint>		RGB32u;
		typedef _color_hidden_::RGBi<ulong>		RGB64u;
		typedef _color_hidden_::RGBi<byte>		RGB8i;
		typedef _color_hidden_::RGBi<short>		RGB16i;
		typedef _color_hidden_::RGBi<int>		RGB32i;
		typedef _color_hidden_::RGBi<ilong>		RGB64i;

		typedef _color_hidden_::RGBAi<ubyte>	RGBA8u;
		typedef _color_hidden_::RGBAi<ushort>	RGBA16u;
		typedef _color_hidden_::RGBAi<uint>		RGBA32u;
		typedef _color_hidden_::RGBAi<ulong>	RGBA64u;
		typedef _color_hidden_::RGBAi<byte>		RGBA8i;
		typedef _color_hidden_::RGBAi<short>	RGBA16i;
		typedef _color_hidden_::RGBAi<int>		RGBA32i;
		typedef _color_hidden_::RGBAi<ilong>	RGBA64i;

		typedef _color_hidden_::RedF<half,		false>	R16f;
		typedef _color_hidden_::RedF<float,		false>	R32f;
		typedef _color_hidden_::RedF<double,	false>	R64f;

		typedef _color_hidden_::RGf<half,		false>	RG16f;
		typedef _color_hidden_::RGf<float,		false>	RG32f;
		typedef _color_hidden_::RGf<double,		false>	RG64f;

		typedef _color_hidden_::RGBf<half,		false>	RGB16f;
		typedef _color_hidden_::RGBf<float,		false>	RGB32f;
		typedef _color_hidden_::RGBf<double,	false>	RGB64f;

		typedef _color_hidden_::RGBAf<half,		false>	RGBA16f;
		typedef _color_hidden_::RGBAf<float,	false>	RGBA32f;
		typedef _color_hidden_::RGBAf<double,	false>	RGBA64f;

		typedef _color_hidden_::RGBA4u<false>			RGBA4u;
		typedef _color_hidden_::RGB5_A1u<false>			RGB5_A1u;
		typedef _color_hidden_::R5_G6_B5u<false>		R5_G6_B5u;
		typedef _color_hidden_::RGBA4u_Rev<false>		RGBA4u_Rev;
		typedef _color_hidden_::RGB5_A1u_Rev<false>		RGB5_A1u_Rev;
		typedef _color_hidden_::R5_G6_B5u_Rev<false>	R5_G6_B5u_Rev;

		typedef _color_hidden_::RGB10_A2u<false>		RGB10_A2u;
		typedef _color_hidden_::RGB10_A2u_Rev<false>	RGB10_A2u_Rev;
		typedef _color_hidden_::R11_G11_B10f<false>		R11_G11_B10f;
		typedef _color_hidden_::RGB9_E5f_Rev<false>		RGB9_E5f_Rev;

		// normalized formats
		typedef _color_hidden_::RedI<ubyte,   true>		R8_UNorm;
		typedef _color_hidden_::RedI<ushort,  true>		R16_UNorm;
		typedef _color_hidden_::RGi<ubyte,    true>		RG8_UNorm;
		typedef _color_hidden_::RGi<ushort,   true>		RG16_UNorm;
		typedef _color_hidden_::RGBi<ubyte,   true>		RGB8_UNorm;
		typedef _color_hidden_::RGBi<ushort,  true>		RGB16_UNorm;
		typedef _color_hidden_::RGBAi<ubyte,  true>		RGBA8_UNorm;
		typedef _color_hidden_::RGBAi<ushort, true>		RGBA16_UNorm;

		typedef _color_hidden_::RGBA4u<true>			RGBA4_UNorm;
		typedef _color_hidden_::RGB5_A1u<true>			RGB5_A1_UNorm;
		typedef _color_hidden_::R5_G6_B5u<true>			R5_G6_B5_UNorm;
		typedef _color_hidden_::RGB10_A2u<true>			RGB10_A2_UNorm;
		typedef _color_hidden_::RGBA4u_Rev<true>		RGBA4_Rev_UNorm;
		typedef _color_hidden_::RGB5_A1u_Rev<true>		RGB5_A1_Rev_UNorm;
		typedef _color_hidden_::R5_G6_B5u_Rev<true>		R5_G6_B5_Rev_UNorm;
		typedef _color_hidden_::RGB10_A2u_Rev<true>		RGB10_A2_Rev_UNorm;

		typedef _color_hidden_::RedI<byte,    true>		R8_SNorm;
		typedef _color_hidden_::RedI<short,   true>		R16_SNorm;
		typedef _color_hidden_::RGi<byte,     true>		RG8_SNorm;
		typedef _color_hidden_::RGi<short,    true>		RG16_SNorm;
		typedef _color_hidden_::RGBi<byte,    true>		RGB8_SNorm;
		typedef _color_hidden_::RGBi<short,   true>		RGB16_SNorm;
		typedef _color_hidden_::RGBAi<byte,   true>		RGBA8_SNorm;
		typedef _color_hidden_::RGBAi<short,  true>		RGBA16_SNorm;

		typedef _color_hidden_::RedF<half,		true>	R16f_Norm;
		typedef _color_hidden_::RedF<float,		true>	R32f_Norm;
		typedef _color_hidden_::RedF<double,	true>	R64f_Norm;

		typedef _color_hidden_::RGf<half,		true>	RG16f_Norm;
		typedef _color_hidden_::RGf<float,		true>	RG32f_Norm;
		typedef _color_hidden_::RGf<double,		true>	RG64f_Norm;

		typedef _color_hidden_::RGBf<half,		true>	RGB16f_Norm;
		typedef _color_hidden_::RGBf<float,		true>	RGB32f_Norm;
		typedef _color_hidden_::RGBf<double,	true>	RGB64f_Norm;

		typedef _color_hidden_::RGBAf<half,		true>	RGBA16f_Norm;
		typedef _color_hidden_::RGBAf<float,	true>	RGBA32f_Norm;
		typedef _color_hidden_::RGBAf<double,	true>	RGBA64f_Norm;

		typedef _color_hidden_::R11_G11_B10f<true>		R11_G11_B10f_Norm;
		typedef _color_hidden_::RGB9_E5f_Rev<true>		RGB9_E5f_Rev_Norm;

	}	// ColorFormat

	namespace ColorFormatUtils
	{
		typedef _color_hidden_::IntFormat				IntFormat;
		typedef	_color_hidden_::FloatFormat				FloatFormat;

		typedef _color_hidden_::IntColorFormatInfo		IntColorFormatInfo;
		typedef _color_hidden_::FloatColorFormatInfo	FloatColorFormatInfo;
		typedef _color_hidden_::ColorFormatConverter	ColorFormatConverter;

		//
		// Color Swizzle
		//

		template <typename T, ubyte R, ubyte G, ubyte B, ubyte A>
		struct ColorSwizzle
		{
		// constants
			static const uint	format		= T::format;
			static const bool	_is_float	= (format & _color_hidden_::EColorFormatDescriptor::FLOAT) != 0;

		// types
			using color_t	= T;
			using Self		= ColorSwizzle< T, R, G, B, A >;
			using format_t	= typename CompileTime::SwitchType<	_is_float, FloatFormat, IntFormat >;
			using info_t	= typename CompileTime::SwitchType< _is_float, FloatColorFormatInfo, IntColorFormatInfo >;

		// variables
			color_t		_color;

		// methods
			ColorSwizzle () {}

			ColorSwizzle (const format_t &c) : _color( format_t( c[R&3], c[G&3], c[B&3], c[A&3] ) ) {}

			operator format_t () const
			{
				format_t	c( _color );
				return format_t( c[R&3], c[G&3], c[B&3], c[A&3] );
			}

			explicit operator info_t () const
			{
				return info_t( _color ).template GetSwizzledFormat< R, G, B, A >();
			}

			template <typename ColorType>
			bool operator == (const ColorType &right) const
			{
				return All( format_t(*this) == format_t(right) );
			}
		};

	}	// ColorFormatUtils

}	// GXMath
}	// GX_STL

{'content_hash': 'fb8b1adbfd9db3877ef0f431ffa9f6c9', 'timestamp': '', 'source': 'github', 'line_count': 1245, 'max_line_length': 118, 'avg_line_length': 29.296385542168675, 'alnum_prop': 0.6348906070077316, 'repo_name': 'azhirnov/GraphicsGenFramework-modular', 'id': '75e006b4765fe32968a3bff4ca6d676038d44d90', 'size': '36474', 'binary': False, 'copies': '1', 'ref': 'refs/heads/master', 'path': 'Core/STL/Math/Color/ColorFormats.h', 'mode': '33188', 'license': 'bsd-2-clause', 'language': [{'name': 'C', 'bytes': '1425521'}, {'name': 'C++', 'bytes': '3919134'}, {'name': 'GLSL', 'bytes': '663'}, {'name': 'HTML', 'bytes': '19783'}, {'name': 'Objective-C', 'bytes': '2740'}]}


Аксел Лунд Свиндал () норвешки је алпски скијаш. Двоструки је победник Светског купа (2007. и 2009) у укупном поретку. Освајач је златне медаље у супервелеслалому на Олимпијским играма у Ванкуверу и у спуст у Пјонгчангу, као и пет златних медаља на светским првенствима (2007, 2009, 2011, 2013) у спусту, велеслалому и комбинацији.

Освојени кристални глобуси

9 (2 укупни победник, 1 у спусту, 4 у супервелеслалому, 1 у велеслалому, 1 у комбинацији)

Победе у Светском купу

35 победа (14 у спусту, 16 у супервелеслалому, 4 у велеслалому, 1 у комбинацији)

Спољашње везе

Профил Аксела Лунда Свиндала на сајту Међународне скијашке федерације

Рођени 1982.
Норвешки алпски скијаши
Алпски скијаши на Зимским олимпијским играма 2006.
Норвешки олимпијци на Зимским олимпијским играма 2006.
Алпски скијаши на Зимским олимпијским играма 2010.
Норвешки олимпијци на Зимским олимпијским играма 2010.
Освајачи медаља на Зимским олимпијским играма 2010.
Алпски скијаши на Зимским олимпијским играма 2014.
Норвешки олимпијци на Зимским олимпијским играма 2014.
Алпски скијаши на Зимским олимпијским играма 2018.
Норвешки олимпијци на Зимским олимпијским играма 2018.
Освајачи медаља на Зимским олимпијским играма 2018.
Освајачи олимпијских медаља у алпском скијању
Освајачи златних олимпијских медаља за Норвешку
Освајачи сребрних олимпијских медаља за Норвешку
Освајачи бронзаних олимпијских медаља за Норвешку
Олимпијски победници у алпском скијању
Светски прваци у алпском скијању


from utils.dict import mget
from utils.string import nstrip,nlower
from utils.property import cached_property
from utils.list import sort
from sanetime import ntime, delta, time
from .base import Base
from giftwrap import JsonExchange
from uuid import uuid4

class Registrant(Base):
    def __init__(self, **kwargs):
        super(Registrant, self).__init__()
        self.webinar = kwargs.get('webinar')
        self.session = kwargs.get('session')
        self.key = mget(kwargs, 'key', 'registrant_key', 'registrantKey')
        self.email = nlower(mget(kwargs, 'email', 'attendeeEmail'))
        self.first_name = mget(kwargs, 'first_name', 'firstName', 'first')
        self.last_name = mget(kwargs, 'last_name', 'lastName', 'last')
        if kwargs.get('name'): self.name = nstrip(kwargs.get('name'))
        self.registered_at = ntime(mget(kwargs, 'registered_at', 'registrationDate'))
        self.join_url = mget(kwargs, 'join_url', 'joinUrl')
        self.status = kwargs.get('status')
        self.viewings = kwargs.get('viewings',[])
        if not self.viewings and kwargs.get('attendance'):
            self.viewings = sort([(time(d['joinTime']),time(d['leaveTime'])) for d in kwargs['attendance']])
        if not self.viewings and (kwargs.get('duration') or kwargs.get('attendanceTimeInSeconds')) and self.session and self.session.key and self.session.started_at:
            duration = kwargs.get('duration') or kwargs.get('attendanceTimeInSeconds') and delta(s=kwargs['attendanceTimeInSeconds'])
            self.viewings = [(self.session.started_at, self.session.started_at+duration)]

    @property
    def name(self): return ('%s %s' % (self.first_name or '', self.last_name or '')).strip()
    @name.setter
    def name(self, n):
        parts = n.split(' ')
        self.first_name = self.first_name or ' '.join(parts[0:-1]).strip() or None
        self.last_name = self.last_name or parts[-1].strip() or None

    @property
    def started_at(self): return self.viewings and self.viewings[0][0] or None

    @property
    def ended_at(self): return self.viewings and self.viewings[-1][-1] or None

    @property
    def duration(self): return self.viewings and (self.viewings[-1][-1] - self.viewings[0][0]) or None

    def merge(self, other):
        self._merge_primitives(other, 'webinar', 'session', 'key', 'email', 'first_name', 'last_name', 'registered_at', 'join_url', 'status')
        viewings = []
        for v in sort(self.viewings + other.viewings):
            if viewings:
                last = viewings[-1]
                if v[0]<=last[-1]:
                    viewings[-1] = (min(v[0],last[0]),max(v[-1],last[-1]))
                    continue
            viewings.append(v)
        self.viewings = viewings
        return self

    def __cmp__(self, other): return self._cmp_components(other, 'email', 'last_name', 'first_name', 'started_at', 'ended_at', 'key', 'registered_at', 'join_url', 'status', 'viewings')

    def clone(self): return Registrant().merge(self)

    def create(self): return self._create_ex.result

    @classmethod
    def _create(kls, registrants): return CreateRegistrant.bulk_results([r._create_ex for r in registrants], async=False)  # otherwise we api rate limits

    @cached_property
    def _create_ex(self): return CreateRegistrant(self)

    def __repr__(self): return str(self)
    def __str__(self): return unicode(self).encode('utf-8')
    def __unicode__(self):
        started_at = self.started_at and "%s +%s" % (time(self.started_at.us,self.timezone).strftime('%m/%d/%y %I:%M%p').lower(), self.timezone) or '?'
        ended_at = self.ended_at and "%s +%s" % (time(self.ended_at.us,self.timezone).strftime('%m/%d/%y %I:%M%p').lower(), self.timezone) or '?'
        registered_at = self.registered_at and "%s +%s" % (time(self.registered_at.us,self.timezone).strftime('%m/%d/%y %I:%M%p').lower(), self.timezone) or '?'
        return u"%s[%s] %s (%s %s) %s [ %s ] (%s - %s) :%s =%s" % (self.started_at and 'A' or 'R', self.key, self.email, self.first_name, self.last_name, self.duration, self.status or '?', started_at, ended_at, registered_at, self.join_url)

    @property
    def timezone(self): return self.session and self.session.timezone or self.webinar and self.webinar.timezone

    @classmethod
    def random(kls, webinar, count=None):
        registrants = []
        for i in xrange(count or 1):
            guid = ''.join(str(uuid4()).split('-'))
            registrants.append( Registrant(
                    webinar=webinar,
                    first_name = u'John %s <>&\xfc\u2603 ' % guid[:8],
                    last_name = u'Smith %s <>&\xfc\u2603 ' % guid[8:16],
                    email = u'%s.%s@%s.com' % (guid[:8].upper(),guid[:8:16],guid[16:])))
        return count is None and registrants[0] or registrants

class RegistrantExchange(JsonExchange):
    def __init__(self, registrant, **kwargs):
        super(RegistrantExchange, self).__init__(registrant.webinar.organizer, **kwargs)
        self.registrant = registrant

class CreateRegistrant(RegistrantExchange):
    method = 'post'
    def sub_path(self): return 'webinars/%s/registrants'%self.registrant.webinar.key
    def python_data(self):
        return { "firstName": self.registrant.first_name, "lastName": self.registrant.last_name, "email": self.registrant.email }
    def process_data(self, data, response):
        return self.registrant.merge(Registrant(**data))
    def process_error(self, error, response):
        return response is not None and response.status_code==409  # just telling us that the registrant already exists-- so it was successful

{'content_hash': '195cdee5e0eed7a124663e8be7285df7', 'timestamp': '', 'source': 'github', 'line_count': 112, 'max_line_length': 240, 'avg_line_length': 50.410714285714285, 'alnum_prop': 0.628409493446688, 'repo_name': 'prior/gtwpy', 'id': 'f3cab62b3f57889c5b99f331de27b7571b8b4b7a', 'size': '5646', 'binary': False, 'copies': '1', 'ref': 'refs/heads/master', 'path': 'gtw/registrant.py', 'mode': '33188', 'license': 'mit', 'language': [{'name': 'Python', 'bytes': '49448'}]}


Карлова Коруна () — замок-дворец начала XVIII века в Чехии, одно из значимых зданий в стиле барокко в стране. Расположен вблизи Хлумца-над-Цидлиной.

История
Заказчиком замка был граф Франц Фердинанд Кински (1668—1741). Высокая должность (он был тогда высочайшим канцлером Чешского королевства) и желание подтвердить свой высокий социальный статус обусловили строительство нового замка.

Проект замка создал архитектор Ян Сантини (1677—1723). Архитектор получил хорошее художественное образование, которое совершенствовал в Италии. Он изучал нетипичные, сложные (по планам и формами) произведения известного итальянского мастера Франческо Борромини и сам был склонен к необычным плановым решениям и насыщенной архитектурной символике.

Строительство
Строительство продолжалось в 1721—1723 годах. Практически это была последняя крупная постройка архитектора, скончавшегося в 1723 году. Ян Сантини и здесь создал необычный образец замка со сложной планировкой. Центром сооружения стал роскошный зал-ротонда, к которому по трём осям пристроены прямоугольные крылья. Небольшое количество помещений компенсировано сложной игрой объёмов — ротонды с куполом, крыш с переломами, закруглённого объёма парадной лестницы.

Нетипичная планировка и отход от привычных удлинённых дворцов с тремя ризалитами на французский манер вызывали недоумение и осуждение. Замок начали считать блажью обладателя и даже свидетельством его глупости. В 1723 году замок посетил император Карл VI, после чего канцлер переименовал замок в Карлову Коруну.

Кроме замка была создана капелла, которую планировали сделать усыпальницей рода Кинских. Капелла воспринимается достаточно самостоятельным объектом, мало связанным с архитектурой замка, как и античная беседка — парковый павильон в стиле классицизма. Постройки окружены пейзажным парком. После смерти Яна Сантини в усадьбе работал архитектор Франц Максимилиан Канка.

XX век
До XX века замок не перестраивали. Во время Второй мировой войны (в 1943 году) здание было повреждено пожаром, но мебель была спасена и передана в другие замки.

В 1968 году замок передали в состав Национальной галереи. Несколько лет продолжалось восстановление и ремонт замка. В помещениях замка развернули выставку «Барокко в Чехии».

В 1992 году имущество и замок Карлова Коруна были возвращены потомкам рода Кински. В замке сейчас экспозиция с рассказом о представителях рода Кински и истории разведения лошадей в городе Хлумец-над-Цидлиной.

Фотогалерея

Примечания

Литература

Ссылки

Замки Краловеградецкого края
Здания и сооружения, построенные в 1723 году

Здания и сооружения, заложенные в 1721 году
XVIII век в Чехии


Handlebar (grip, lever) - トライアンフ / Meriden for TRIUMPH junkies.
Showing [1-17] Items out of  Items.
Copyright© 2011 meriden all right reserved.

{'timestamp': '2019-04-21T11:03:06Z', 'url': 'http://meriden.jp/?mode=cate&cbid=933250&csid=2&sort=p', 'language': 'en', 'source': 'c4'}


A De Zeven Provinciën (jelentése: „a hét tartomány”) több holland építésű hadihajó névadója volt a Holland Királyi Haditengerészetben (KN, Koninklijke Marine; „királyi haditengerészet”), amely az Utrechti unióval létre jövő Holland Köztársaságot alkotó hét tartományt jelöli (a hadihajók névelője időben változott Zr.Ms. és Hr.Ms. között, a mindenkori holland uralkodótól függően):

 De Zeven Provinciën (1643) – az Amszterdami admiralitás sorhajója
 De Zeven Provinciën (1665) – a Maeze-i (rotterdami) admiralitás 80 ágyús sorhajója, amely a második és a harmadik angol–holland háborúban Michiel de Ruyter tengernagy zászlóshajója
 De Zeven Provinciën (1694) – a Maeze-i (rotterdami) admiralitás sorhajója
 De Zeven Provinciën (1782) – a Noorderkwartier (Nyugat-frieslandi) admiralitás sorhajója
 De Zeven Provinciën (1909) – partvédő hajó, amely 1910 és 1942 között állt csapatszolgálatban
 De Zeven Provinciën (C802) – a De Zeven Provinciën osztály (cirkálók) egyik cikrálója
 De Zeven Provinciën (F802) – a De Zeven Provinciën osztály (fregattok) egyik fregattja.

{'title': 'De Zeven Provinciën (egyértelműsítő lap)', 'url': 'https://hu.wikipedia.org/wiki/De%20Zeven%20Provinci%C3%ABn%20%28egy%C3%A9rtelm%C5%B1s%C3%ADt%C5%91%20lap%29', 'language': 'hu', 'timestamp': '20230320'}


Ingeborg Fülepp rođena je u Zagrebu u Hrvatskoj i hrvatska je medijska umjetnica, predavačica na visokim školama, kuratorica i filmska montažerka.

Životopis
Studirala je Filmsku montažu na Akademiji za kazalište i film (kasnije nazvanoj Akademijom dramskih umjetnosti (ADU) na Sveučilištu u Zagrebu) i kasnije pedagogiju, video produkciju te interaktivne tehnologije kod Carol Chomsky i Howarda Gardnera na sveučilištu Harvard, sveučilištu u Cambridgeu (SAD) i kod Richarda Leacocka i Gloriana Davenporta na Massachusetts Institute of Technology, The Media Laboratory (MIT) u Bostonu (SAD).

Stvaralački rad
Sudjelovala je kao montažerka slike i zvuka na brojnim jugoslavenskim filmskim i televizijskim produkcijama te na međunarodnim koprodukcijama. Godine 1978. započela je karijeru prvo kao asistentica profesora na ADU u Zagrebu, a zatim i kao docentica te gostujuća profesorica u Londonu, Bostonu, Nizozemskoj, Austriji i Njemačkoj, primjerice na Njemačkoj visokoj školi za film i televiziju Berlin (DFFB) i na Visokoj školi za film i televiziju Potsdam-Babelsberg Konrad Wolf. Od 1997. godine do danas radi na Visokoj školi za tehniku i ekonomiju u Berlinu (FHTW). Od 2013. godine izvanredna je profesorica na Akademiji primijenjene umjetnosti Sveučilišta u Rijeci. Od 2013. do 2016. godine vršila je funkciju prodekanice za međunarodnu suradnju.

Od 1990. do 2012. godine, sa suprugom i suradnikom Heikom Daxlom pod imenom mediainmotion i dafü®, radila je na području kulture, filma, videa, interaktivnih medija i multimedijskih projekata, videoumjetnosti te videoinstalacija. Još za vrijeme rata, od 1993. godine, u Zagrebu su zajedno organizirali hrvatske skupove i niz izložbi pod nazivom Media-Scape s međunarodnim umjetnicima i teoretičarima medijske umjetnosti, a između ostalih i u Muzeju suvremene umjetnosti u Zagrebu do 1999. i od 2005. godine s Jericom Ziherl u Galeriji Rigo i Muzeju Lapidarium u Novigradu/Cittánovi u Istri. Godine 2006. ovaj je program u suradnji s Noamom Braslavskyjem proširen pod nazivom Strictly Berlin u Galerie der Künste (GdK) u Berlinu. Od 2013. godine (nakon smrti supruga i partnera Heika Daxla) organizira razne medijske izložbe u Hrvatskoj i Njemačkoj.

Osim umjetničkog, pedagoškog i kuratorsko-organizacijskog djelovanja, surađivali su i s Das Studio für Elektroakustische Musik na Akademie der Künste (Berlin) (od 1996. do 2002.) gdje su u okviru koncertnih i kazališnih predstava surađivali s kompozitorima suvremene umjetnosti poput Georga Katzera, Wolfganga Rihma, Hans-Joachima Hesposa te ansamblom Zeitkratzer, a na video projektima s kompozitorima kao što su Frano Parač, Jorge Reyes, Steve Roach, Suso Saiz, Bert Wrede, Zbigniew Karkowski, Valerio Pizzorno i Igor Kuljerić.

Doktorica Barbara Barsch, ravnateljica ifa-galerije berlinskog Instituta za odnose s inozemstvom (Izvodak iz teksta u katalogu Tuned Graphics, Galerija RIGO, 2005.)

Ingeborg Fülepp živi i radi u Rijeci, Berlinu i Zagrebu.

Stipendije
 Goethe-Institut, Schwäbisch-Hall (Njemačka),1982.
 Joyce and Zlatko Balokovic Fund/Jugoslavenska akademija znanosti i umjetnosti, Zagreb, 1985./1986.
 Edmund J. Curley Fellowship, Harvard University (SAD), 1987./1988.
 William Schuman Fellowship, Harvard University (SAD), 1987./1988.
 Goethe-Institut, Berlin (Njemačka), 1992
 Ministarstvo Kulture (Ministerium für Kultur), Zagreb (Hrvatska), 1993. – 1999.
 Ministerium für Kultur, Hannover (Njemačka), 1993. – 1996.
 Sommerakademie, Akademie der Künste, Berlin (Njemačka),1997.
 Auswärtiges Amt, Bonn (Njemačka), 1997./1998.
 Male Promjene, grad Zagreb (Hrvatska), 1999.
 Institut für Auslandsbeziehungen (IFA), Stuttgart (Njemačka), 2001.

Nagrade i priznanja
 Prevost, Jugoslavenski festival igranog filma u Puli u filmu Luda kuċa za Filmsku montažu, 1979.
 Prix du public, Lausanne filmu Posvećenje mjesta (Filmska montaža), 1987.
 Grand Prix, Paris i "UNESCO Festival Award" filmu Posvećenje mjesta (Filmska montaža), 1990.
 Velika srebrna Arena, Jugoslavenski festival igranog filma u Puli filmu Ljeto za sjećanje (Filmska montaža)1990.
 Max Ophüls Preis, Saarbrücken filmu Müde Weggefährten (Filmska montaža), 1997.

Vanjske poveznice
 fuelepp.com
 Ingeborg Fülepp/Heiko Daxl
 Mediainmotion Videochannel
 Ingeborg Fülepp na Imdb
 Ingeborg Fülepp na artfacts.net

Multimedijalni umjetnici
Hrvatski filmski montažeri

{'title': 'Ingeborg Fülepp', 'url': 'https://hr.wikipedia.org/wiki/Ingeborg%20F%C3%BClepp', 'language': 'hr', 'timestamp': '20230320'}


<?php

namespace AlainSchlesser\Speaking;

$event_display = empty( $this->talk->get_event_link() )
	? $this->talk->get_event_name()
	: "talk->get_event_link()}\">{$this->talk->get_event_name()}";

?>
<?= __('Event:', 'as-speaking' ) ?> <?= $event_display ?>
	<?= __('Edit', 'as-speaking' ) ?>
		<?= __('Edit event', 'as-speaking' ) ?>

		<input type="hidden" name="hidden_talk_cpt_event_name" id="hidden_talk_cpt_event_name" value="<?= $this->talk->get_event_name() ?>">
		<input type="hidden" name="hidden_talk_cpt_event_link" id="hidden_talk_cpt_event_link" value="<?= $this->talk->get_event_link() ?>">
		<?= __('Name of the event:', 'as-speaking' ) ?>
		<input type="text" id="talk_cpt_event_name" name="talk_cpt_event_name" value="<?= $this->talk->get_event_name() ?>">
		<?= __('URL the event should link to:', 'as-speaking' ) ?>
		<input type="text" id="talk_cpt_event_link" name="talk_cpt_event_link" value="<?= $this->talk->get_event_link() ?>">
		<?= __( 'OK', 'as-speaking' ) ?>
		<?= __( 'Cancel', 'as-speaking' ) ?>

{'content_hash': '4e390eacf0535375ae9b5f05de2c7bbc', 'timestamp': '', 'source': 'github', 'line_count': 23, 'max_line_length': 169, 'avg_line_length': 73.26086956521739, 'alnum_prop': 0.6308605341246291, 'repo_name': 'schlessera/as-speaking', 'id': 'fb5151bb8ed4c375800ea2d6c8b26e22542bb36a', 'size': '1934', 'binary': False, 'copies': '1', 'ref': 'refs/heads/master', 'path': 'views/talk-metabox-event.php', 'mode': '33188', 'license': 'mit', 'language': [{'name': 'CSS', 'bytes': '2336'}, {'name': 'JavaScript', 'bytes': '33123'}, {'name': 'PHP', 'bytes': '111701'}]}


Published 04/21/2019 06:58:47 pm at 04/21/2019 06:58:47 pm in Camo Rubber Boots.
camo rubber boots irish setter by red wing shoes womens rutmaster realtree xtra green camo rubber boots round camo rubber boots canada.
camo rubber boots amazon,camo rubber boots fleet farm,camo rubber boots womens,camo rubber boots walmart,womens camo rubber boots,cabela s camo cross 5mm fleece rubber boots,camo rubber boots for kids,under armour camo rubber boots,mens camo rubber boots,lacrosse camo rubber boots,black rubber boots for sale.

{'timestamp': '2019-04-21T22:58:47Z', 'url': 'http://pkhomchuk.info/camo-rubber-boots/camo-rubber-boots-irish-setter-by-red-wing-shoes-womens-rutmaster-realtree-xtra-green-camo-rubber-boots-round-camo-rubber-boots-canada/', 'language': 'en', 'source': 'c4'}


Ка́ссерин, Касерин () — вилайет в Тунисе.
 Административный центр — город Кассерин (Касерин).
 Площадь — , население —

География
На севере граничит с вилайетом Эль-Кеф, на северо-востоке с вилайетом Сильяна, на востоке с вилайетом Сиди-Бу-Зид, на юге с вилайетом Гафса, на западе с Алжиром.

На территории вилайета находятся национальный парк Джебель-Шамби с самой высокой горой Туниса Шамби 1544 м и римские развалины в Хайдре.

Административное деление
Вилайет Касерин делится на 13 округов:
 Эль-Аюн (El Ayoun)
 Эззухур (Ezzouhour)
 Фериана (Fériana)
 Фусана (Foussana)
 Хайдра (Haïdra)
 Хасси-эль-Ферид (Hassi El Ferid)
 Джедельен (Jedelienne)
 Северный Касерин (Kasserine Nord)
 Южный Касерин (Kasserine Sud)
 Бордж-Маджин-Бу-эль-Аббес (Majel Bel Abbès)
 Сбейтла (Sbeïtla)
 Сбиба (Sbiba)
 Тала (Thala)

Примечания


__БЕЗКН__

Black or White је био први хит сингл са албума -{Dangerous}- објављеног октобра 1991. године пјевача Мајкла Џексона.

Пјесма је мјешавина денса, хард рока и репа.

Провела је на првом мјесту билборд топ сто хитова чак седам недјеља.

Музику и текст је написао сам Џексон, а реп дио Бил Ботрел, док увод пјесме изводи славни гитариста Слеш.
"-{Black or White}-" је пјесма која говори о једнакости раса.

Спот
У споту "-{Black or White}-" се поред Џексона појављују Меколи Калкин, Тес Харпер, Џорџ Венд и супермодел Тајра Бенкс.
Спот је режирао Џон Лендис који је такође одговоран за чувени Џексонов спот "-{Thriller}-".

Постоје двије верзије спота: дужа и краћа. Дужа приказује Џексона који све вријеме плеше, док у посљедње четири најконтроверзније минуте пјевач лупа прозоре, уништава аутомобил и ствари које симболизују нацизам, укључујући и кукасти крст.

Пошто је спот изазвао бурне реакције због Џексонових насилних покрета од којих неки садрже велику дозу сексуалности, пјевач је касније објаснио како је у питању опонашање инстинкта црног пантера у кога се сам претвара у току спота.

Позиције

__БЕЗКН__

Синглови Мајкла Џексона
Песме 1991.
Синглови 1991.
Синглови на првом месту листе UK Singles Chart
Синглови на првом месту листе Билборд хот 100

{'title': 'Black or White', 'url': 'https://sr.wikipedia.org/wiki/Black%20or%20White', 'language': 'sr', 'timestamp': '20230320'}


Cerkiew Świętych Borysa i Gleba – prawosławna cerkiew w Kidiekszy, zabytek wpisany na Listę Światowego Dziedzictwa UNESCO.

Historia
Za tradycyjną datę wzniesienia cerkwi przyjmuje się – według informacji zawartych w latopisie – 1152, zaś jako fundatora – Jurija Dołgorukiego. W literaturze przedmiotu występują różne oceny datowania świątyni. Część autorów przychyla się do danych z latopisu bądź przesuwa moment jej budowy na koniec lat 50. XII wieku, inni zaś uważają, że świątynia mogła powstać w dowolnym momencie między końcem lat 40. XII wieku a schyłkiem następnej dekady. Obiekt wznieśli budowniczowie z ziemi halickiej. Cerkiew najprawdopodobniej była częścią większego kompleksu zamkowego z rezydencją Jurija Dołgorukiego i umocnieniami. Konstrukcje te jednak nie przetrwały do naszych czasów. W XIV w. przy świątyni istniał również męski monaster, zlikwidowany przed XVIII stuleciem.

Na przełomie XVI–XVII wieku stan techniczny świątyni (zwłaszcza dachu) był na tyle zły, że w latach 60. XVII wieku rozebrano jej absydy, zaś pierwotną kopułę zastąpiono znacznie mniejszą konstrukcją. W takiej postaci cerkiew przetrwała do naszych czasów.

Cerkiew Świętych Borysa i Gleba należy do obiektów włodzimiersko-suzdalskiego muzeum-rezerwatu, chroniącego zabytki architektury staroruskiej na ziemi włodzimierskiej. Jest wpisana na listę Światowego Dziedzictwa UNESCO.

Architektura
Cerkiew Świętych Borysa i Gleba jest budowlą wzniesioną na planie czworoboku (pierwotnie z trzema absydami), z jedną kopułą. Budynek w całości zbudowano z sześciennych bloków białego kamienia. Obiekt nie posiada niemal żadnej dekoracji zewnętrznej. We wnętrzu zachowały się częściowo freski.

Przypisy

Obiekty z listy dziedzictwa UNESCO w Rosji
Cerkwie eparchii włodzimierskiej
Świątynie pod wezwaniem Świętych Borysa i Gleba
Kidieksza, Borys i Gleb

{'title': 'Cerkiew Świętych Borysa i Gleba w Kidiekszy', 'url': 'https://pl.wikipedia.org/wiki/Cerkiew%20%C5%9Awi%C4%99tych%20Borysa%20i%20Gleba%20w%20Kidiekszy', 'language': 'pl', 'timestamp': '20230320'}


oogst
 De oogst (Bruegel), schilderij uit 1565
 De oogst (Jan Heyens), beeldhouwwerk
 De oogst (Van Gogh), schilderij

{'title': 'De oogst', 'url': 'https://nl.wikipedia.org/wiki/De%20oogst', 'language': 'nl', 'timestamp': '20230320'}


Projekt Chang’e – ogłoszony w 2003 roku chiński program bezzałogowych i załogowych badań Księżyca. Przewiduje on realizację trzech etapów do 2020 r.:

 Umieszczenie na orbicie Księżyca orbiterów Chang’e 1 i Chang’e 2, wystrzelonych w latach 2007 i 2010 z kosmodromu Xichang. Miały one za zadanie sporządzenie trójwymiarowej mapy powierzchni Srebrnego Globu, zbadanie rozkładu i ilości pierwiastków w gruncie księżycowym, zmierzenie gęstości powierzchni Księżyca oraz monitorowanie środowiska w otoczeniu Księżyca.
 Umieszczenie na powierzchni Księżyca za pomocą sond Chang’e 3 i Chang’e 4 łazików przeznaczonych do badań powierzchni skał i gruntu księżycowego.
 Umieszczenie na powierzchni Księżyca za pomocą sond Chang’e 5 i Chang’e 6 lądowników ze statkami powrotnymi, które dostarczą próbki gleby księżycowej.

Nazwa projektu podchodzi od imienia chińskiej bogini Księżyca, Chang’e.

Do wynoszenia tych sond wykorzystywane są rakiety rodziny Chang Zheng 3, natomiast ostatni etap będzie wymagał nowej, silniejszej rakiety nośnej Chang Zheng 5, która ma być gotowa w 2015 r.

Misje
 Chang’e 1 – październik 2007 – orbiter
 Chang’e 2 – październik 2010 – orbiter
 Chang’e 3 – grudzień 2013 – lądownik z łazikiem
 Chang’e 5-T1 – październik 2014 – test aparatu powrotnego sondy Chang’e-5 po wykonaniu oblotu Księżyca
 Chang’e 4 – 2019 – lądownik z łazikiem
 Chang’e 5 – 2020 – lądownik z powrotnikiem
 Chang’e 6 – 2023/2024 – lądownik z powrotnikiem

Przypisy

Bibliografia

 Loty Kosmiczne

{'title': 'Program Chang’e', 'url': 'https://pl.wikipedia.org/wiki/Program%20Chang%E2%80%99e', 'language': 'pl', 'timestamp': '20230320'}