HTC Mozart не видит домашнюю Wi-Fi сеть: решение

Разное

Tagged Under : , ,

Недавно приобрёл HTC Mozart. Телефон домашнюю Wi-Fi сеть увидел сразу же как появился на пороге дома и проблем с подключением к ней не наблюдалось.

Всё бы хорошо, но сегодня утром телефон при подключении по Wi-Fi перестал показывать домашнюю сеть среди нескольких доступных. Проанализировав всё, что я делал (на ночь я роутер d-link 815 выключал) подозрение пало на роутер. Проверив настройки Wi-Fi проблем я не обнаружил, погуглив наткнулся на обсуждение следующей темы на форуме поддержки HTC: Проблема с WiFi – не видит некоторые точки доступа.

Учитывая, что в настройках роутера у меня был выбран пункт Enable Auto Channel Selection, я решил чётко установить номер канал и снять автоматический выбор (при включении как раз и происходит выбор канала, видимо был выбран канал «не с тем номером»).

Данные действия помогли и домашняя сеть снова появилась в списке доступных. Оказалось это вроде как особенность аппаратов от HTC.

Orchard CMS: интегрируем Uppod

Программирование

Tagged Under : ,

Итак, появилась необходимость добавить для сайта на базе Orchard CMS, модуль для проигрывания mp3-файлов. Выбранный модуль jPlayer, к сожалению, уронил весь сайт. Не решившись более рисковать решил создать свой модуль на базе плеера Uppod (не факт, конечно, что мой не роняет :) ). С ним я работаю давно, поэтому долго не выбирал.

Процедура создания модуля отличается от других примеров создания модулей на данном сайте тем, что в рамках модуля мы будем активно использовать шорткоды, функционал которых добавляется на сайт путём добавления моего модуля kosfiz.Shortcodes, создание которого описано в записи «Orchard CMS: добавляем поддержку shortcodes«.

Итак, прежде всего необходимо создать модуль, и затем открыть проект с ним. Далее, в папку Models добавляем класс UppodSettingsRecord описывающий настройки плеера, распространяющиеся на весь сайт:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace kosfiz.Uppod.Models
{
    public class UppodSettingsRecord
    {
        public virtual int Id { get; set; }
        public virtual string VideoPlayerStyle { get; set; }
        public virtual int VideoPlayerWidth { get; set; }
        public virtual int VideoPlayerHeight { get; set; }
        public virtual string AudioPlayerStyle { get; set; }
        public virtual int AudioPlayerWidth { get; set; }
        public virtual int AudioPlayerHeight { get; set; }
        public virtual string PhotoPlayerStyle { get; set; }
        public virtual int PhotoPlayerWidth { get; set; }
        public virtual int PhotoPlayerHeight { get; set; }
        public virtual string BackgroundColor { get; set; }
    }
}

Данный класс описывает размеры и стили для каждого из видов плееров (видео, аудио, фото), а также цвет фона.
Потом отражаем свойства описанные в классе в базу посредством класса Migrations

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.Data.Migration;
using System.Data;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Core.Contents.Extensions;

namespace kosfiz.Uppod
{
    public class Migrations : DataMigrationImpl
    {
        public int Create()
        {
            SchemaBuilder.CreateTable("UppodSettingsRecord", table => table.Column("Id", DbType.Int32, column => column.PrimaryKey().Identity())
                .Column("VideoPlayerStyle", DbType.String, column => column.Nullable())
                .Column("VideoPlayerWidth", DbType.Int32, column => column.NotNull().WithDefault(400))
                .Column("VideoPlayerHeight", DbType.Int32, column => column.NotNull().WithDefault(300))
                .Column("AudioPlayerStyle", DbType.String, column => column.Nullable())
                .Column("AudioPlayerWidth", DbType.Int32, column => column.NotNull().WithDefault(300))
                .Column("AudioPlayerHeight", DbType.Int32, column => column.NotNull().WithDefault(90))
                .Column("PhotoPlayerStyle", DbType.String, column => column.Nullable())
                .Column("PhotoPlayerWidth", DbType.Int32, column => column.NotNull().WithDefault(400))
                .Column("PhotoPlayerHeight", DbType.Int32, column => column.NotNull().WithDefault(300))
                .Column("BackgroundColor", DbType.String, column => column.NotNull().WithDefault("ffffff"))
                );

            return 1;
        }
    }
}

Указываем имена полей, типы данных, и значения по умолчанию, а также обязательность. Дальше создаём папку Services и в неё добавляем интерфейс IUppodService и класс, реализующий данный интерфейс UppodService. Данный класс содержит методы обновления и получения настроек плеера, а также метод, который будет вызываться на обработку шорткода uppod. Последний и представляет наибольший интерес:

public static string UppodRender(Dictionary<string, object> atts)
{
    string type = "video";
    if (atts.ContainsKey("type"))
        type = (string)atts["type"];

    string file = string.Empty;
    string playlist = string.Empty;
    if (atts.ContainsKey("files"))
    {
        file = (string)atts["files"];
        if (file.Contains(","))
        {
            playlist = "{ 'playlist' : [" + string.Join(", ", file.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x=> "{" + string.Format(""file":"{0}"", x) + "}").ToList()) + "] }";
            file = string.Empty;
        }
    }

    var settings = GetSettings();

    int width = 0;
    int height = 0;
    string style = string.Empty;
    switch (type)
    {
        case "audio":
            width = settings.AudioPlayerWidth;
            height = settings.AudioPlayerHeight;
            style = settings.AudioPlayerStyle;
            break;
        case "video":
            width = settings.VideoPlayerWidth;
            height = settings.VideoPlayerHeight;
            style = settings.VideoPlayerStyle;
            break;
        case "photo":
            width = settings.PhotoPlayerWidth;
            height = settings.PhotoPlayerHeight;
            style = settings.PhotoPlayerStyle;
            break;
        default:
            break;
    }

    if(atts.ContainsKey("width"))
        width = (int)atts["width"];

   
    if (atts.ContainsKey("height"))
        height = (int)atts["height"];

    string Poster = string.Empty;
    if (atts.ContainsKey("poster"))
        Poster = (string)atts["poster"];

    string Comment = string.Empty;
    if (atts.ContainsKey("comment"))
        Comment = (string)atts["comment"];

    Random rnd = new Random();
    string playerId = "uplayer_" + rnd.Next(0, 10000);

    StringBuilder flashvars = new StringBuilder();
    flashvars.Append("{");
    flashvars.AppendFormat(""m":"{0}","
    + ""uid":"{1}","
    + ""{2}": "{3}""
    + "{4}"
    + "{5}"
    + "{6}", type, playerId, string.IsNullOrEmpty(file) ? "pl" : "file", string.IsNullOrEmpty(file) ? playlist.Replace(""", "'") : file,
    string.IsNullOrEmpty(style) ? "" : ", "st" : "" + style + """, string.IsNullOrEmpty(Poster) ? "" : string.Format(", "poster" : "{0}"", Poster),
    string.IsNullOrEmpty(Comment) ? "" : string.Format(", "comment" : "{0}"", Comment));
    flashvars.Append("}");

    StringBuilder flashparams = new StringBuilder();
    flashparams.Append("{");
    flashparams.AppendFormat("id:"{0}", "
    + "bgcolor:"#{1}", allowFullScreen:"true", allowScriptAccess:"always"", playerId, settings.BackgroundColor);
    flashparams.Append("}");

    StringBuilder htmlparams = new StringBuilder();
    htmlparams.Append("{");
    htmlparams.AppendFormat("m: "{0}", comment: "{1}", uid: "{2}", {3} : "{4}"", type, string.IsNullOrEmpty(Comment) ? "" : Comment,
        playerId, string.IsNullOrEmpty(file) ? "pl" : "file", string.IsNullOrEmpty(file) ? playlist.Replace(""", "'
") : file);
    htmlparams.Append("
}");

    string div = string.Format("
<div id="{0}" style="width:{1}px; height:{2}px;"></div>", playerId, width, height);
    string script = string.Format("
<script type="text/javascript">init("{0}", {1}, {2}, {3}, {4}, {5})</script>", playerId, flashvars, flashparams, htmlparams, width, height);

    return string.Format("
{0}<br/>{1}", div, script);
}

Данный метод добавляет в страницу вместо шорткода div и скрипт вызывающий инициализацию плеера. Сама функция инициализации (и другие) содержится в скрипте и выглядит следующим образом:

function initUppodFlashPlayer(playerId, flashvars, flashparams, width, height) {
    swfobject.embedSWF("/Modules/kosfiz.Uppod/Scripts/uppod.swf", playerId, width, height, "9.0.115", false, flashvars, flashparams);
}

function initHtml5Player(htmlparams) {
    var v = document.createElement('video');
    if (v.canPlayType('video/mp4')) {
        this.vplayer = new Uppod(htmlparams);
    }
    else { }

}
function init(playerId, flashvars, flashparams, htmlparams, width, height) {
    var playerVersion = swfobject.getFlashPlayerVersion();

    if (playerVersion.major >= 9)
        initUppodFlashPlayer(playerId, flashvars, flashparams, width, height);
    else
        initUppodHtml5Player(htmlparams);
}

Другие файлы необходимые для работы плеера добавляем в папку Scripts: uppod.js (html5-версия), uppod.swf (плеер), swfobject (вдруг ещё не добавлен), uppod_init.js (содержимое приведено выше).

Теперь надо добавить скрипты в код страницы и добавить шорткод uppod и метод для его обработки в словарь шорткодов. Для этого добавляем папку Handlers и в него класс UppodHandler:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.ContentManagement.Handlers;
using kosfiz.Uppod.Models;
using Orchard.Data;
using Orchard;
using Orchard.UI.Resources;
using Orchard.Caching;
using kosfiz.UppodServices;
using kosfiz.Shortcodes.Models;

namespace kosfiz.Uppod.Handlers
{
    public class UppodHandler: ContentHandler
    {
        readonly IWorkContextAccessor _workContextAccessor;
        public UppodHandler(IWorkContextAccessor workContextAccessor, IRepository<UppodSettingsRecord> repository, ICacheManager cacheManager, ISignals signals)
        {
            try
            {
                _workContextAccessor = workContextAccessor;
                var resourceManager = _workContextAccessor.GetContext().Resolve<IResourceManager>();
                var links = resourceManager.GetRegisteredLinks();
                bool uppod = false;
                bool swfobject = false;
                foreach (var link in links)
                {
                    if (link.Href.ToLower().Contains("uppod"))
                        uppod = true;
                    if (link.Href.ToLower().Contains("swfobject"))
                        swfobject = true;
                }

                if (!swfobject)
                    resourceManager.RegisterHeadScript("<script type="text/javascript" src="/Modules/kosfiz.Uppod/Scripts/swfobject-2.2.min.js"></script>");
                if (!uppod)
                {
                    resourceManager.RegisterHeadScript("<script type="text/javascript" src="/Modules/kosfiz.Uppod/Scripts/uppod.js"></script>");
                    resourceManager.RegisterHeadScript("<script type="text/javascript" src="/Modules/kosfiz.Uppod/Scripts/uppod_init.js"></script>");
                }
            }
            finally
            {
                ShortCodeService.AddShortCode("uppod", UppodService.UppodRender); //добавляем шорткод в список обрабатываемых, указывая в какой метод передавать параметры
                UppodService uppodService = new UppodService(repository, cacheManager, signals);
            }
        }
    }
}

На этом программирование основного функционала можно считать законченным, осталось лишь добавить код для внесения настроек модуля в админку.
Добавляем AdminMenu в корень проекта

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.UI.Navigation;
using Orchard.Localization;

namespace kosfiz.Uppod
{
    public class AdminMenu : INavigationProvider
    {
        public Localizer T { get; set; }

        public AdminMenu()
        {
            T = NullLocalizer.Instance;
        }

        public void GetNavigation(NavigationBuilder builder)
        {
            builder.Add(T("Uppod"), "49", menu => menu.Add(T("Uppod"), "0", item => item.Action("Index", "Admin", new { area = "kosfiz.Uppod" })));
        }

        public string MenuName
        {
            get { return "admin"; }
        }
    }
}

Осталось добавить контроллер и представление, соответственно:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Orchard.UI.Admin;
using kosfiz.Uppod.ViewModels;
using kosfiz.Uppod.Services;
using Orchard;
using Orchard.Localization;

namespace kosfiz.Uppod.Controllers
{
    [ValidateInput(false), Admin]
    public class AdminController: Controller
    {
        private readonly IUppodService _uppodService;
       
        public IOrchardServices Services { get; set; }
        public Localizer T { get; set; }

        public AdminController(IOrchardServices services, IUppodService uppodService)
        {
            Services = services;
            _uppodService = uppodService;
        }

        [HttpGet]
        public ActionResult Index()
        {
            var m = _uppodService.Get();
            UppodSettingsViewModel model = new UppodSettingsViewModel { AudioPlayerHeight = m.AudioPlayerHeight, AudioPlayerStyle = m.AudioPlayerStyle, AudioPlayerWidth = m.AudioPlayerWidth, BackgroundColor = m.BackgroundColor, VideoPlayerHeight = m.VideoPlayerHeight, VideoPlayerStyle = m.VideoPlayerStyle, VideoPlayerWidth = m.VideoPlayerWidth, PhotoPlayerHeight = m.PhotoPlayerHeight, PhotoPlayerStyle = m.PhotoPlayerStyle, PhotoPlayerWidth = m.PhotoPlayerWidth };
            return View(model);
        }

        [HttpPost]
        public ActionResult Index(UppodSettingsViewModel model)
        {
            if (ModelState.IsValid)
            {
                _uppodService.Set(model.VideoPlayerStyle, model.VideoPlayerWidth, model.VideoPlayerHeight, model.AudioPlayerStyle, model.AudioPlayerWidth, model.AudioPlayerHeight, model.PhotoPlayerStyle, model.PhotoPlayerWidth, model.PhotoPlayerHeight, model.BackgroundColor);
                return RedirectToAction("Index");
            }
           
            return View();
        }
    }
}
@model kosfiz.Uppod.ViewModels.UppodSettingsViewModel

<h1>@Html.TitleForPage(@T("Manage Uppod settings").ToString())</h1>
@using (Html.BeginFormAntiForgeryPost())
{
    <fieldset>
    <table>
        <tr>
            <td>@T("Background color"):</td>
            <td>
                @Html.TextBoxFor(model=>model.BackgroundColor)
            </td>
        </tr>
        <tr>
            <td colspan="3">
                <h2>@T("Video")</h2>
            </td>
        </tr>
        <tr>
            <td>@T("Style"):</td>
            <td>
                @Html.TextBoxFor(model=>model.VideoPlayerStyle)
            </td>
        </tr>
        <tr>
            <td>@T("Width"):</td>
            <td>
                @Html.TextBoxFor(model=>model.VideoPlayerWidth)
            </td>
        </tr>
        <tr>
            <td>@T("Height"):</td>
            <td>
                @Html.TextBoxFor(model=>model.VideoPlayerHeight)
            </td>
        </tr>
        <tr>
            <td colspan="3">
                <h2>@T("Audio")</h2>
            </td>
        </tr>
        <tr>
            <td>@T("Style"):</td>
            <td>
                @Html.TextBoxFor(model=>model.AudioPlayerStyle)
            </td>
        </tr>
        <tr>
            <td>@T("Width"):</td>
            <td>
                @Html.TextBoxFor(model=>model.AudioPlayerWidth)
            </td>
        </tr>
        <tr>
            <td>@T("Height"):</td>
            <td>
                @Html.TextBoxFor(model=>model.AudioPlayerHeight)
            </td>
        </tr>
        <tr>
            <td colspan="3">
                <h2>@T("Photo")</h2>
            </td>
        </tr>
        <tr>
            <td>@T("Style"):</td>
            <td>
                @Html.TextBoxFor(model=>model.PhotoPlayerStyle)
            </td>
        </tr>
        <tr>
            <td>@T("Width"):</td>
            <td>
                @Html.TextBoxFor(model=>model.PhotoPlayerWidth)
            </td>
        </tr>
        <tr>
            <td>@T("Height"):</td>
            <td>
                @Html.TextBoxFor(model=>model.PhotoPlayerHeight)
            </td>
        </tr>

    </table>
    <input type="submit" value="@T("Save")" title="@T("Save")" />
    </fieldset>
}

Остаётся только собрать модуль.

Ссылка на модуль

Оба модуля успешно используются, к примеру, здесь: http://school286.ru/odod-voenno-patrioticheskoe

P.S.: CodeColorer «любезно» во вставках кода подтёр кое-что в тех местах, где идёт работа со строками, так что лучше смотреть код в модуле.

Orchard CMS: добавляем поддержку shortcodes

Программирование

Tagged Under : , ,

Shortcodes должны быть известны пользователям блогов на WordPress: с помощью шорткодов можно добавить свой функционал прямо в текст статьи. Это, на мой взгляд, необходимость.

Например, плагин подсветки CodeColorer, который использую я. Аналогичный функционал понадобился бы при реализации спойлер-блоков, как, например, в статье на сайте kanobu.ru. Применений можно найти множество.

Данной возможности в Orchard CMS по умолчанию не наблюдается: там всё по заранее настроенному порядку, т.е. один тип контента нельзя вставить внутрь другого, нельзя добавить несколько одинаковых типов контента к статье (допустим несколько галерей). Это, естественно, ограничивает разработчиков и, как следствие, конечных пользователей.

Итак, задача, которую нужно прежде всего решить, это программно переопределить Parts.Common.Body.cshtml таким образом, чтобы в ней обрабатывались шорткоды.

Пошагово процесс выглядит следующим образом:

  • Добавить класс, описывающий шорткод
  • Реализовать класс, через который можно будет добавлять шорткоды и методы их обрабатывающие. Реализовать в рамках класса простейший парсер шорткодов и отрисовку
  • Переопределить Parts.Common.Body.cshtml

Создадим модуль и откроем его проект в Visual Studio или другой среде разработки. В папку Modules добавляем класс ShortCodeItem со следующим содержимым:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace kosfiz.Shortcodes.Models
{
    public class ShortCodeItem
    {
        private string codeName = string.Empty;
        public string CodeName
        {
            get
            {
                return codeName;
            }
            set
            {
                codeName = value;
            }
        }

        private int startIndex;
        public int StartIndex
        {
            get
            {
                return startIndex;
            }
            set
            {
                startIndex = value;
            }
        }

        private int endIndex;
        public int EndIndex
        {
            get
            {
                return endIndex;
            }
            set
            {
                endIndex = value;
            }
        }

        public string TargetText
        {
            get;
            set;
        }

        public string SourceText
        {
            get;
            set;
        }
    }
}

На следующем шаге добавляем ShortCodeService, который и будет выполнять основные функции.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace kosfiz.Shortcodes.Models
{
    public class ShortCodeService
    {
        //здесь будем хранить все шорткоды и методы, их обрабатывающие
        static Dictionary<string, Func<Dictionary<string, object>, string>> Methods = new Dictionary<string, Func<Dictionary<string, object>, string>>();

        //метод добавления шорткода
        public static void AddShortCode(string ShortCodeName, Func<Dictionary<string, object>, string> method)
        {
            if (!Methods.ContainsKey(ShortCodeName)) //если шорткод уже есть, то игнорируем его
                Methods.Add(ShortCodeName, method);
        }

        //выполняем метод соответсвующий имени шорткода и передаём ему параметры, сторонний метод должен принимать на выход словарь строка = объект
        private static string DoMethod(string ShortCodeName, Dictionary<string, object> atts)
        {
            return Methods[ShortCodeName].Invoke(atts);
        }

        //из текста выбирает шорткоды
        private static List<ShortCodeItem> GetShortCodes(string Text)
        {
            List<ShortCodeItem> codes = new List<ShortCodeItem>();

            foreach (var item in Methods)
            {
                try
                {
                    string startTag = string.Format("[{0}", item.Key);
                    string endTag = string.Format("[/{0}]", item.Key);

                    int startIndex = Text.IndexOf(startTag);
                    while (startIndex != -1)
                    {
                        int endIndex = Text.IndexOf(endTag, startIndex);
                        if (endIndex != -1)
                        {
                            int paramsEndIndex = Text.IndexOf("]", startIndex);
                            if (paramsEndIndex != -1)
                            {
                                string source = Text.Substring(startIndex + startTag.Length, paramsEndIndex - startIndex - startTag.Length);
                                Dictionary<string, object> atts = GetValues(source, paramsEndIndex + 1, endIndex - paramsEndIndex - 1, Text);
                                codes.Add(new ShortCodeItem { CodeName = item.Key, StartIndex = startIndex, EndIndex = endIndex, TargetText = DoMethod(item.Key, atts), SourceText = Text.Substring(startIndex, endIndex + endTag.Length - startIndex) });
                            }
                        }
                        startIndex = Text.IndexOf(startTag, startIndex + 1);
                    }
                }
                catch (Exception) { }
            }

            return codes;
        }

        //формируем словарь параметров шорткода
        private static Dictionary<string, object> GetValues(string source, int InnerStart, int InnerEnd, string InnerText)
        {
            Dictionary<string, object> values = new Dictionary<string, object>();

            int paramNameIndex = source.IndexOf("=");
            int lastParamValueIndex = 0;
            while (paramNameIndex != -1)
            {
                string attrName = source.Substring(0, paramNameIndex);
                string attrValue = string.Empty;
                if (source[paramNameIndex + 1] != '"')
                {
                    lastParamValueIndex = source.IndexOf(" ", paramNameIndex + 1);
                    if (lastParamValueIndex == -1)
                        lastParamValueIndex = source.Length - 1;
                    attrValue = source.Substring(paramNameIndex + 1, lastParamValueIndex - paramNameIndex);
                }
                else
                {
                    lastParamValueIndex = source.IndexOf("\"", paramNameIndex + 2);
                    if (lastParamValueIndex == -1)
                        lastParamValueIndex = source.Length - 1;
                    attrValue = source.Substring(paramNameIndex + 2, lastParamValueIndex - paramNameIndex - 2);
                }

                values.Add(attrName.Trim(), attrValue.Trim());
                source = source.Remove(0, lastParamValueIndex);
                paramNameIndex = source.IndexOf("=");
            }
            //InnerHtml предопределённый параметр, содержит содержимое тегов шорткода [shortcodeName]InnerHtml[/shortcodeName]
            values.Add("InnerHtml", InnerText.Substring(InnerStart, InnerEnd).Trim());
            return values;
        }

        //заменяем теги шорткодов на html сгенерированный модулями
        public static MvcHtmlString Render(string Text)
        {
            List<ShortCodeItem> codes = GetShortCodes(Text);
            foreach (var item in codes)
                Text = Text.Replace(item.SourceText, item.TargetText);
            return MvcHtmlString.Create(Text);
        }
    }
}

Собственно, парсер обрабатывает шорткод теги вида:
[shortcodeName attr1=value attr2="value with whitespace or =" attr3=value2]different text[/shortcodeName]

Т.е. необходим закрывающий шорткод тег, значения с пробелом или = заключается в двойные кавычки. Содержимое между открывающим и закрывающим шорткодами передаётся во внешний метод по ключу InnerHtml.

Осталось переопределить Parts.Common.Body.cshtml. Для этого добавляем в папку Views проекта копию оригинального файла и меняем его содержимое на следующее:

@using kosfiz.Shortcodes.Models;
@{
    var body = ShortCodeService.Render(Model.Html.ToString());
}
@body

Далее добавляем в папку Models класс ShortCodeShapeProvider

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.DisplayManagement.Descriptors;
using Orchard;
using Orchard.ContentManagement;

namespace kosfiz.Shortcodes.Models
{
    public class ShortCodeShapeProvider : IShapeTableProvider
    {
        private readonly IWorkContextAccessor _workContextAccessor;
        public ShortCodeShapeProvider(IWorkContextAccessor workContextAccessor)
        {
            _workContextAccessor = workContextAccessor;
        }

        public void Discover(ShapeTableBuilder builder)
        {
            builder.Describe("Parts_Common_Body").OnDisplaying(displaying =>
            {
                ContentItem item = displaying.Shape.ContentItem;
                if (displaying.ShapeMetadata.DisplayType == "Detail")
                {
                    displaying.ShapeMetadata.Alternates.Add("Parts_Common_Body");
                }
            });
        }
    }
}

Вот собственно и всё. Пример создания модуля использующего шорткоды описан в статье «Ссылка на модуль

И снова мозголомки

Разное

Tagged Under :

Итак, у меня имеется две мозголомки: простая и не очень.

  • Eсть два одинаковых кошелька, в каждом по монете. Как сделать так, чтобы в одном из них было две монеты? Вынимать монеты нельзя/
  • Условие
    Итак, представьте себе военное время. В океане передвигается грузовой корабль под охраной двух крейсеров. Идут корабли строем: крейсер, грузовой корабль, крейсер. Враг стреляет торпедой в центр грузового корабля. При попадании в центр гибнет корабль и весь экипаж. Если торпеда не попадает в центр – экипаж спасён.
    Вопрос
    Какие действия предприняли бы вы, если бы были капитаном грузового судна?
    Ограничения
    40-е годы прошлого столетия.

На вторую задачу есть много вариантов решения, предлагайте даже те, в которых не уверены и которые могут быть нереальны.

P.S.: ответы на первую задачу будут в понедельник (21.11), ваши варианты относительно второй буду публиковать сразу же.

Update
По условию второй задачи: гребни волн от торпеды становятся видны метров за 10-15. Грузовое судно тяжёлое, неповоротливое. Подлодка стреляет с боку, т.е. перпендикулярно ходу судна. Расчёт выстрела торпеды учитывает скорость хода судна и течение.

Update 2
Судно грузовое, перемещение команды по нему не поможет. Сбить нельзя торпеду, нет вооружения на судне.

Update 3
Вот для примера, пара вариантов ответов:

  • Учитель географии одной из школ Санкт-Петербурга: вылить в воду жидкий азот перед торпедой
  • Тоже от учителей: попытаться закинуть магнит такой мощности, чтобы он притянул к себе торпеду

Несколько детских мозголомок

Образование

Tagged Under :

Позволю себе отойти от основной тематики блога и опубликовать пару детских задачек мозголомок.

  1. Как бросить сырое куриное яйцо на 4 метра и не разбить? Вы не можете использовать какие-либо предметы кроме яйца.
  2. В комнате есть две тонкие, лёгкие верёвки, свисающие от потолка до пола. Нижний конец обеих верёвок не закреплён. Расположены они так, что взяв конец одной из них и подойдя ко второй вы не сможете дотянуться до второй верёвки рукой.

    Задача состоит в том, чтобы придумать способы взять обе верёвки в руки. Повторюсь способов несколько.
    Взять верёвку можно только руками, т.е. варианты с дотягиванием линейкой или другим предметом отвергаются сразу.

Есть вопросы или варианты ответов? Пишите в комментарии, их первым увижу я и опубликую только либо неправильные варианты либо имена ответивших правильно.