text:
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */

package net.mikaboshi.intra_mart.tools.log_stats.formatter;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.mikaboshi.intra_mart.tools.log_stats.Application;
import net.mikaboshi.intra_mart.tools.log_stats.parser.ParserParameter;
import net.mikaboshi.intra_mart.tools.log_stats.report.GrossStatistics.RequestEntry;
import net.mikaboshi.intra_mart.tools.log_stats.report.PageTimeStat;
import net.mikaboshi.intra_mart.tools.log_stats.report.Report;
import net.mikaboshi.intra_mart.tools.log_stats.report.Report.ExceptionReportEntry;
import net.mikaboshi.intra_mart.tools.log_stats.report.Report.RequestUrlReportEntry;
import net.mikaboshi.intra_mart.tools.log_stats.report.Report.SessionReportEntry;
import net.mikaboshi.intra_mart.tools.log_stats.report.ReportParameter;
import net.mikaboshi.intra_mart.tools.log_stats.report.TenantStatistics;
import net.mikaboshi.intra_mart.tools.log_stats.report.TimeSpanStatistics;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * FreeMarkerのテンプレートを使用して、レポートを生成する。
 *
 * @version 1.0.18
 * @author cwan
 */
public class TemplateFileReportFormatter extends AbstractFileReportFormatter {

	private static final Log logger = LogFactory.getLog(TemplateFileReportFormatter.class);

	private static final Pattern JSSPS_URL_PATTERN = Pattern.compile(".*/(.+?)\\.jssp[s|(rpc)]?.*");

	/** テンプレートファイル */
	private File templateFile = null;

	/** テンプレートファイルパス */
	private String templeteResourceFilePath = null;

	/** カスタムテンプレートファイルの文字コード */
	private String templateFileCharset = Charset.defaultCharset().toString();

	/** 項目の区切り文字 */
	private String separator = null;

	/**
	 * コンストラクタ
	 * @param output レポートの出力先
	 * @param charset レポートの文字コード
	 * @param parserParameter パーサパラメータ
	 * @param reportParameter レポートパラメータ
	 */
	public TemplateFileReportFormatter(
			File output,
			String charset,
			ParserParameter parserParameter,
			ReportParameter reportParameter) {

		super(output, charset, parserParameter, reportParameter);
	}

	/**
	 * レポートの文字コードはシステムデフォルトを使用するコンストラクタ。
	 * @param output レポートの出力先
	 * @param parserParameter パーサパラメータ
	 * @param reportParameter レポートパラメータ
	 */
	public TemplateFileReportFormatter(
				File output,
				ParserParameter parserParameter,
				ReportParameter reportParameter) {

		super(output, parserParameter, reportParameter);
	}

	/**
	 * テンプレートファイルを設定する。
	 * @param templateFile
	 * @throws FileNotFoundException
	 */
	public void setTemplateFile(File templateFile) throws FileNotFoundException {

		if (!templateFile.exists() || !templateFile.isFile()) {
			throw new FileNotFoundException(templateFile.getPath());
		}

		this.templateFile = templateFile;
	}

	/**
	 * テンプレートファイルパス(リソース)を設定する。
	 * @param templeteResourceFilePath
	 * @since 1.0.8
	 */
	public void setTempleteResourceFilePath(String templeteResourceFilePath) {
		this.templeteResourceFilePath = templeteResourceFilePath;
	}

	/**
	 * カスタムテンプレートファイルの文字コードを設定する。
	 * @param templateFileCharset
	 */
	public void setTemplateFileCharset(String templateFileCharset) {
		this.templateFileCharset = templateFileCharset;
	}

	/**
	 * 項目の区切り文字を設定する。
	 * @param separator
	 * @since 1.0.8
	 */
	public void setSeparator(String separator) {
		this.separator = separator;
	}

	@Override
	public void doFormat(Report report) throws IOException {

		Configuration fmConfig = new Configuration();

		InputStream in = null;
		Reader reader = null;

		try {

			if (this.templateFile != null) {

				in = new BufferedInputStream(new FileInputStream(this.templateFile));
				reader = new InputStreamReader(in, this.templateFileCharset);

			} else if (this.templeteResourceFilePath != null) {

				in = new BufferedInputStream(getClass().getResourceAsStream(this.templeteResourceFilePath));
				reader = new InputStreamReader(in, this.templateFileCharset);

			} else {
				throw new IOException("Neither 'templateFile' nor 'templeteResourceFilePath' is set.");
			}

			Template template = new Template("im-memory", reader, fmConfig);

			Map<String, Object> rootMap = new HashMap<String, Object>();

			rootMap.put("charset", this.charset);
			rootMap.put("reportName", report.getParameter().getName());
			rootMap.put("signature", report.getParameter().getSignature());
			rootMap.put("generatedTime", new Date());
			rootMap.put("separator", this.separator);
			rootMap.put("totalPageTime", report.getTotalPageTime());
			rootMap.put("totalRequestCount", report.getRequestCount());
			rootMap.put("projectVersion", Application.getInstance().getProjectVersion());
			rootMap.put("projectUrl", Application.getInstance().getProjectUrl());
			rootMap.put("timeZone", TimeZone.getDefault());

			setParameters(rootMap);
			setTimeSpanStatistics(report, rootMap);
			setRequestPageTimeRank(report, rootMap);
			setRequestUrlRank(report, rootMap);
			setSessionRank(report, rootMap);
			setTenantStatistics(report, rootMap);
			setExceptionRank(report, rootMap);
			setLogFiles(report, rootMap);

			template.process(rootMap, this.writer);

		} catch (TemplateException e) {
			logger.error(e.getMessage(), e);
			throw new IOException(e.getMessage());
		} finally {
			IOUtils.closeQuietly(reader);
			IOUtils.closeQuietly(in);
		}
	}

	/**
	 * パラメータを設定する。
	 * @param rootMap
	 */
	private void setParameters(Map<String, Object> rootMap) {

		rootMap.put("parserParameter", this.parserParameter);
		rootMap.put("reportParameter", this.reportParameter);
	}

	/**
	 * 期間別統計を設定する。
	 * @param report
	 * @param rootMap
	 */
	private void setTimeSpanStatistics(Report report, Map<String, Object> rootMap) {

		report.countActiveSessions();

		Map<String, Object> timeSpanStat = new HashMap<String, Object>();
		rootMap.put("timeSpanStat", timeSpanStat);

		timeSpanStat.put("span", report.getParameter().getSpan());

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		timeSpanStat.put("list", list);

		for (TimeSpanStatistics stat : report.getTimeSpanStatisticsList()) {

			Map<String, Object> row = new HashMap<String, Object>();
			list.add(row);

			List<Long> pageTimes = stat.getRequestPageTimes();

			PageTimeStat pageTimeStat = new PageTimeStat();
			Report.setPageTimeStat(pageTimeStat, pageTimes);

			row.put("startDate", stat.getStartDate());
			row.put("endDate", stat.getEndDate());
			row.put("requestCount", stat.getRequestCount());
			row.put("pageTimeSum", pageTimeStat.pageTimeSum);
			row.put("pageTimeAverage", pageTimeStat.pageTimeAverage);
			row.put("pageTimeMin", pageTimeStat.pageTimeMin);
			row.put("pageTimeMedian", pageTimeStat.pageTimeMedian);
			row.put("pageTimeP90", pageTimeStat.pageTimeP90);
			row.put("pageTimeMax", pageTimeStat.pageTimeMax);
			row.put("pageTimeStandardDeviation", pageTimeStat.pageTimeStandardDeviation);
			row.put("uniqueUserCount", stat.getUniqueUserCount());
			row.put("uniqueSessionCount", stat.getUniqueSessionCount());
			row.put("activeSessionCount", stat.getActiveSessionCount());
			row.put("exceptionCount", stat.getExceptionCount());
			row.put("transitionCount", stat.getTransitionCount());
			row.put("transitionExceptionCount", stat.getTransitionExceptionCount());
			row.put("maxConcurrentRequestCount", stat.getMaxConcurrentRequest());
		}
	}

	/**
	 * リクエスト処理時間のランキング(総合トップN)を設定する。
	 * @param report
	 * @param rootMap
	 */
	private void setRequestPageTimeRank(Report report, Map<String, Object> rootMap) {

		Map<String, Object> requestPageTimeRank = new HashMap<String, Object>();
		rootMap.put("requestPageTimeRank", requestPageTimeRank);

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		requestPageTimeRank.put("list", list);

		requestPageTimeRank.put("size", report.getParameter().getRequestPageTimeRankSize());
		requestPageTimeRank.put("requestCount", report.getRequestCount());

		for (RequestEntry req : report.getRequestPageTimeRank()) {

			if (req == null) {
				continue;
			}

			Map<String, Object> row = new HashMap<String, Object>();
			list.add(row);

			row.put("requestUrl", req.url);
			row.put("requestPageTime", req.time);
			row.put("date", req.date);
			row.put("sessionId", req.sessionId);
			row.put("userId", report.getUserIdFromSessionId(req.sessionId, ""));

			if (reportParameter.isJsspPath()) {
				row.put("jsspPath", getJsspPath(req.url));
			}
		}
	}

	/**
	 * リクエスト処理時間のランキング(URL別・処理時間合計トップN)を設定する。
	 * @param report
	 * @param rootMap
	 */
	private void setRequestUrlRank(Report report, Map<String, Object> rootMap) {

		Map<String, Object> requestUrlRank = new HashMap<String, Object>();
		rootMap.put("requestUrlRank", requestUrlRank);

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		requestUrlRank.put("list", list);

		List<RequestUrlReportEntry> reportList = report.getRequestUrlReportList();

		requestUrlRank.put("size", report.getParameter().getRequestUrlRankSize());
		requestUrlRank.put("total", reportList.size());

		MathContext percentMathContext = new MathContext(2, RoundingMode.HALF_UP);

		int i = 0;

		for (RequestUrlReportEntry entry : reportList) {

			if (++i > report.getParameter().getRequestUrlRankSize()) {
				break;
			}

			Map<String, Object> row = new HashMap<String, Object>();
			list.add(row);

			row.put("url", entry.url);
			row.put("count", entry.count);
			row.put("pageTimeSum", entry.pageTimeSum);
			row.put("pageTimeAverage", entry.pageTimeAverage);
			row.put("pageTimeMin", entry.pageTimeMin);
			row.put("pageTimeMedian", entry.pageTimeMedian);
			row.put("pageTimeP90", entry.pageTimeP90);
			row.put("pageTimeMax", entry.pageTimeMax);
			row.put("pageTimeStandardDeviation", entry.pageTimeStandardDeviation);
			row.put("countRate", new BigDecimal(entry.countRate * 100, percentMathContext).doubleValue());
			row.put("pageTimeRate", new BigDecimal(entry.pageTimeRate * 100, percentMathContext).doubleValue());

			if (reportParameter.isJsspPath()) {
				row.put("jsspPath", getJsspPath(entry.url));
			}
		}
	}

	/**
	 * リクエスト処理時間のランキング(セッション別・処理時間合計トップN)を設定する。
	 * @param report
	 * @param rootMap
	 */
	private void setSessionRank(Report report, Map<String, Object> rootMap) {

		Map<String, Object> sessionRank = new HashMap<String, Object>();
		rootMap.put("sessionRank", sessionRank);

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		sessionRank.put("list", list);

		List<SessionReportEntry> reportList = report.getSessionReportList();

		sessionRank.put("size", report.getParameter().getSessionRankSize());
		sessionRank.put("total", reportList.size());

		MathContext percentMathContext = new MathContext(2, RoundingMode.HALF_UP);

		int i = 0;

		for (SessionReportEntry entry : reportList) {

			if (++i > report.getParameter().getSessionRankSize()) {
				break;
			}

			Map<String, Object> row = new HashMap<String, Object>();
			list.add(row);

			row.put("sessionId", entry.sessionId);
			row.put("userId", report.getUserIdFromSessionId(entry.sessionId, ""));
			row.put("count", entry.count);
			row.put("pageTimeSum", entry.pageTimeSum);
			row.put("pageTimeAverage", entry.pageTimeAverage);
			row.put("pageTimeMin", entry.pageTimeMin);
			row.put("pageTimeMedian", entry.pageTimeMedian);
			row.put("pageTimeP90", entry.pageTimeP90);
			row.put("pageTimeMax", entry.pageTimeMax);
			row.put("pageTimeStandardDeviation", entry.pageTimeStandardDeviation);
			row.put("countRate", new BigDecimal(entry.countRate * 100, percentMathContext).doubleValue());
			row.put("pageTimeRate", new BigDecimal(entry.pageTimeRate * 100, percentMathContext).doubleValue());
			row.put("firstAccessTime", entry.firstAccessTime);
			row.put("lastAccessTime", entry.lastAccessTime);
		}
	}

	/**
	 * テナント別統計を設定する。
	 * @since 1.0.16
	 * @param report
	 * @param rootMap
	 */
	private void setTenantStatistics(Report report, Map<String, Object> rootMap) {

		Map<String, Object> tenantStat = new HashMap<String, Object>();
		rootMap.put("tenantStat", tenantStat);

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		tenantStat.put("list", list);

		for (TenantStatistics stat : report.getTenantStatisticsList()) {

			Map<String, Object> row = new HashMap<String, Object>();
			list.add(row);

			List<Long> pageTimes = stat.getRequestPageTimes();

			PageTimeStat pageTimeStat = new PageTimeStat();
			Report.setPageTimeStat(pageTimeStat, pageTimes);

			row.put("tenantId", stat.getTenantId());
			row.put("requestCount", stat.getRequestCount());
			row.put("pageTimeSum", pageTimeStat.pageTimeSum);
			row.put("pageTimeAverage", pageTimeStat.pageTimeAverage);
			row.put("pageTimeMin", pageTimeStat.pageTimeMin);
			row.put("pageTimeMedian", pageTimeStat.pageTimeMedian);
			row.put("pageTimeP90", pageTimeStat.pageTimeP90);
			row.put("pageTimeMax", pageTimeStat.pageTimeMax);
			row.put("pageTimeStandardDeviation", pageTimeStat.pageTimeStandardDeviation);
			row.put("uniqueUserCount", stat.getUniqueUserCount());
			row.put("uniqueSessionCount", stat.getUniqueSessionCount());
			row.put("exceptionCount", stat.getExceptionCount());
			row.put("transitionCount", stat.getTransitionCount());
			row.put("transitionExceptionCount", stat.getTransitionExceptionCount());
			row.put("maxConcurrentRequestCount", stat.getMaxConcurrentRequest());
		}
	}

	/**
	 * 例外回数を設定する。
	 * @param report
	 * @param rootMap
	 */
	private void setExceptionRank(Report report, Map<String, Object> rootMap) {

		List<Map<String, Object>> exceptionList = new ArrayList<Map<String, Object>>();
		rootMap.put("exceptionList", exceptionList);

		for (ExceptionReportEntry e : report.getExceptionReport()) {

			Map<String, Object> row = new HashMap<String, Object>();
			exceptionList.add(row);

			row.put("level", e.level);
			row.put("message", e.message);
			row.put("groupingLineOfStackTrace", e.groupingLineOfStackTrace);
			row.put("count", e.count);
		}
	}

	/**
	 * 解析対象ログファイルを設定する。
	 * @param report
	 * @param rootMap
	 */
	private void setLogFiles(Report report, Map<String, Object> rootMap) {

		Map<String, Object> logFiles = new HashMap<String, Object>();
		rootMap.put("logFiles", logFiles);

		logFiles.put("requestLogFiles",
				report.getRequestLogFiles() != null ?
				report.getRequestLogFiles() :
				ListUtils.EMPTY_LIST);

		logFiles.put("transitionLogFiles",
				report.getTransitionLogFiles() != null ?
				report.getTransitionLogFiles() :
				ListUtils.EMPTY_LIST);

		logFiles.put("exceptionLogFiles",
				report.getExceptionLogFiles() != null ?
				report.getExceptionLogFiles() :
				ListUtils.EMPTY_LIST);

		logFiles.put("transitionLogOnly",
				CollectionUtils.isEmpty(report.getRequestLogFiles()));
	}

	/**
	 * JSSPページパスを取得する。
	 * @param url
	 * @return
	 * @since 1.0.11
	 */
	private String getJsspPath(String url) {

		if (url == null) {
			return StringUtils.EMPTY;
		}

		Matcher matcher = JSSPS_URL_PATTERN.matcher(url);

		if (!matcher.matches()) {
			return StringUtils.EMPTY;
		}

		String path = matcher.group(1);

		path = StringUtils.replace(path, "(2f)", "/");
		path = StringUtils.replace(path, "(5f)", "_");

		return path;
	}
}


text:
#import "THTTPClient.h"
#import "TTransportException.h"

@implementation THTTPClient

- (void) setupRequest
{
  if (mRequest != nil) {
    [mRequest release];
  }

  // set up our request object that we'll use for each request
  mRequest = [[NSMutableURLRequest alloc] initWithURL: mURL];
  [mRequest setHTTPMethod: @"POST"];
  [mRequest setValue: @"application/x-thrift" forHTTPHeaderField: @"Content-Type"];
  [mRequest setValue: @"application/x-thrift" forHTTPHeaderField: @"Accept"];

  NSString * userAgent = mUserAgent;
  if (!userAgent) {
    userAgent = @"Cocoa/THTTPClient";
  }
  [mRequest setValue: userAgent forHTTPHeaderField: @"User-Agent"];

  [mRequest setCachePolicy: NSURLRequestReloadIgnoringCacheData];
  if (mTimeout) {
    [mRequest setTimeoutInterval: mTimeout];
  }
}

- (id) initWithURL: (NSURL *) aURL
{
  return [self initWithURL: aURL
                 userAgent: nil
                   timeout: 0];
}

- (id) initWithURL: (NSURL *) aURL
         userAgent: (NSString *) userAgent
           timeout: (int) timeout
{
  self = [super init];
  if (!self) {
    return nil;
  }

  mTimeout = timeout;
  if (userAgent) {
    mUserAgent = [userAgent retain];
  }
  mURL = [aURL retain];

  [self setupRequest];

  // create our request data buffer
  mRequestData = [[NSMutableData alloc] initWithCapacity: 1024];

  return self;
}

- (void) setURL: (NSURL *) aURL
{
  [aURL retain];
  [mURL release];
  mURL = aURL;

  [self setupRequest];
}

- (void) dealloc
{
  [mURL release];
  [mUserAgent release];
  [mRequest release];
  [mRequestData release];
  [mResponseData release];
  [super dealloc];
}

- (int) readAll: (uint8_t *) buf offset: (int) off length: (int) len
{
  NSRange r;
  r.location = mResponseDataOffset;
  r.length = len;

  [mResponseData getBytes: buf+off range: r];
  mResponseDataOffset += len;

  return len;
}

- (void) write: (const uint8_t *) data offset: (unsigned int) offset length: (unsigned int) length
{
  [mRequestData appendBytes: data+offset length: length];
}

- (void) flush
{
  [mRequest setHTTPBody: mRequestData]; // not sure if it copies the data

  // make the HTTP request
  NSURLResponse * response;
  NSError * error;
  NSData * responseData =
    [NSURLConnection sendSynchronousRequest: mRequest returningResponse: &response error: &error];

  [mRequestData setLength: 0];

  if (responseData == nil) {
    @throw [TTransportException exceptionWithName: @"TTransportException"
                                reason: @"Could not make HTTP request"
                                error: error];
  }
  if (![response isKindOfClass: [NSHTTPURLResponse class]]) {
    @throw [TTransportException exceptionWithName: @"TTransportException"
                                           reason: [NSString stringWithFormat: @"Unexpected NSURLResponse type: %@",
                                                    NSStringFromClass([response class])]];
  }

  NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *) response;
  if ([httpResponse statusCode] != 200) {
    @throw [TTransportException exceptionWithName: @"TTransportException"
                                           reason: [NSString stringWithFormat: @"Bad response from HTTP server: %ld",
                                                    (long)[httpResponse statusCode]]];
  }

  // phew!
  [mResponseData release];
  mResponseData = [responseData retain];
  mResponseDataOffset = 0;
}

@end

redpajama_set_name: RedPajamaGithub


text:
enum { NameLabel = 1, NameEdit, ModalButton, ShoutCheckbox, MessageLabel };

static HDWP moveCtrl(HDWP dwp, HWND wnd, int id, int x, int y, int w, int h) {
  auto ctrl = curt::getDlgItem(wnd, id);
  return DeferWindowPos(dwp, ctrl, nullptr, x, y, w, h, SWP_NOZORDER);
}

static void createControls(HWND wnd) {
  curt::createStatic(wnd, NameLabel);
  curt::createEdit(wnd, NameEdit);
  curt::createButton(wnd, ModalButton);
  curt::createCheckbox(wnd, ShoutCheckbox);
  curt::createStatic(wnd, MessageLabel);

  curt::setControlToDefaultFont(wnd, NameLabel);
  curt::setControlToDefaultFont(wnd, NameEdit);
  curt::setControlToDefaultFont(wnd, ModalButton);
  curt::setControlToDefaultFont(wnd, ShoutCheckbox);
  curt::setControlToDefaultFont(wnd, MessageLabel);
}

static void resizeWindow(HWND wnd, int w, int h) {
  const auto p = 11;
  const auto labelToEdit = 5;
  const auto editToButton = 9;

  auto dwp = BeginDeferWindowPos(5);

  auto y = p;
  dwp = moveCtrl(dwp, wnd, NameLabel, p, y, w - 2 * p, 13);
  y += 13;

  y += labelToEdit;
  dwp = moveCtrl(dwp, wnd, NameEdit, p, y, w - 2 * p - editToButton - 75, 23);
  dwp = moveCtrl(dwp, wnd, ModalButton, w - p - 75 - 1, y - 1, 75 + 2, 23 + 2);
  y += 23;

  y += p;
  dwp = moveCtrl(dwp, wnd, ShoutCheckbox, p, y, w - 2 * p, 17);
  y += 17;

  y += p;
  dwp = moveCtrl(dwp, wnd, MessageLabel, p, y, w - 2 * p, h - p - y);

  EndDeferWindowPos(dwp);
}

static LRESULT CALLBACK
MainViewProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  try {
    switch (msg) {
    case WM_CREATE:
      createControls(wnd);
      break;
    case WM_SIZE:
      resizeWindow(wnd, LOWORD(lParam), HIWORD(lParam));
      break;
    }

    return curt::defWindowProc(wnd, msg, wParam, lParam);
  }
  catch (...) {
    curt::saveCurrentException();
    return 0;
  }
}

static ATOM registerMainView() {
  auto wcex = WNDCLASSEXW{ sizeof(WNDCLASSEXW) };

  wcex.lpfnWndProc = &MainViewProc;
  wcex.hInstance = curt::thisModule();
  wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
  wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
  wcex.lpszClassName = L"uiglue main view";
  wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_UIGLUE);
  wcex.hIcon = LoadIconW(curt::thisModule(), MAKEINTRESOURCEW(IDI_UIGLUE));
  wcex.hIconSm = LoadIconW(curt::thisModule(), MAKEINTRESOURCEW(IDI_SMALL));

  return curt::registerClassEx(&wcex);
}

namespace uiglue {

curt::Window makeMainView() {
  static auto classAtom = registerMainView();

  const auto x = CW_USEDEFAULT; // All dimensions are default

  auto mainView = curt::createWindowEx(WS_EX_APPWINDOW,
                                       classAtom,
                                       nullptr,
                                       WS_OVERLAPPEDWINDOW,
                                       x,
                                       x,
                                       x,
                                       x,
                                       HWND_DESKTOP,
                                       nullptr,
                                       curt::thisModule(),
                                       nullptr);

  curt::subclassControlBackground(mainView, RGB(255, 255, 255));
  curt::subclassAppView(mainView);

  declareBindings(mainView)
    (uiglue::ThisView, "title", curt::loadString(IDS_APP_TITLE))
    (uiglue::MenuCommand, IDM_ABOUT, "onAbout")
    (uiglue::MenuCommand, IDM_EXIT, "onExit")
    (NameLabel, "text", "Name:")
    (NameEdit, "value", "bind: name")
    (ModalButton, "text", "Modal")
    (ModalButton, "click", "onModalGreeting")
    (ShoutCheckbox, "text", "Shout")
    (ShoutCheckbox, "checked", "bind: shout")
    (MessageLabel, "text", "bind: greeting")
  ;

  return mainView;
}

} // end namespace uiglue


text:
/*globals equal,test*/
Ink.requireModules(['Ink.UI.FormValidator_2', 'Ink.Dom.Element_1', 'Ink.Dom.Selector_1', 'Ink.Util.Array_1', 'Ink.Dom.Event_1', 'Ink.Dom.Css_1'], function (FormValidator, InkElement, Selector, InkArray, InkEvent, Css) {
    'use strict';

    function makeForm(options) {
        options = Ink.extendObj({
            makeValidator: true
        }, options || {});

        var form = document.body.appendChild(InkElement.create('form', {
            className: 'ink-form',
            method: 'POST',
            action: 'http://local'
        }));

        var controlGroup = form.appendChild(InkElement.create('div', {
            id: 'element_26',
            className: 'control-group required',
            'data-rules': 'required'
        }));

        var control = controlGroup.appendChild(InkElement.create('div', {
            className: 'control'
        }));

        var newInput = control.appendChild(InkElement.create('input', {
            id: 'radio2',
            type: 'radio'
        }));

        if (options.makeValidator) {
            var validator = new FormValidator(form, options)
        }

        return {
            form: form,
            validator: validator || null,
            controlGroup: controlGroup,
            control: control
        }
    }

    // Reparse all the fields in the form validator
    function reparse(formVal) {
        var formElements = formVal.getElements()
        for (var key in formElements) {
            if (formElements.hasOwnProperty(key)) {
                for (var j = 0; j < formElements[key].length; j++) {
                    formElements[key][j]._parseRules(
                        formElements[key][j]._element.getAttribute('data-rules')
                    );
                }
            }
        }
    }

    test('(regression): should destroy FormElement instances after using them', sinon.test(function () {
        var o = makeForm()

        var myForm = o.form
        var validator = o.validator

        var initFunc = this.spy(FormValidator.FormElement.prototype, '_init');
        validator.validate();
        validator.validate();
        equal(initFunc.callCount, 1, 'FormElement#_init only called once');

        myForm.parentNode.removeChild(myForm);
    }));

    test('Error messages', function () {
        var formPack = makeForm();

        var form = formPack.form;
        var validator = formPack.validator;

        form.innerHTML = '';

        form.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'FIELD1NAME',
            'data-rules': 'required'
        }));

        form.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'field2name',
            'data-rules': 'required',
            'data-error': 'ERROR TEXT'
        }));

        ok(!validator.validate(), 'sanity check');

        var tips = Ink.ss('p.tip', form);

        equal(tips.length, 2,
            'there should be 2 error paras')

        ok(/FIELD1NAME/.test(
            InkElement.textContent(tips[0])))
        equal(InkElement.textContent(tips[1]), 'ERROR TEXT')
    });

    test('languages', function() {
        var form = makeForm();
        form.validator.setLanguage('pt_PT');
        equal(form.validator.getLanguage(), 'pt_PT');
        notEqual(FormValidator.getI18n(), form.validator.getI18n());
        equal(form.validator.getI18n().lang(), 'pt_PT');
    })

    test('Skips validating matches fields just as long as their matched field is not required', function () {
        var oldStuff = makeForm();

        var myForm = oldStuff.form;
        var validator = oldStuff.validator;

        myForm.innerHTML = '';

        myForm.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'password',
            'data-rules': 'required'
        }));

        myForm.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'passwordconfirmation',
            'data-rules': 'matches[password]'
        }));

        var elms = validator.getElements();

        reparse(validator);

        equal(elms.passwordconfirmation[0].validate(), false, 'Empty password matching field is invalid because the password is required');

        elms.password[0]._element.setAttribute('data-rules', '');

        reparse(validator);

        equal(elms.passwordconfirmation[0].validate(), true, 'Empty password matching field is valid because the password is not required');
    });

    test('Skips validating fields when they\'re empty, but still validates them if required', function () {
        var oldStuff = makeForm();

        var myForm = oldStuff.form;
        var validator = oldStuff.validator;

        myForm.innerHTML = '';

        myForm.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'number',
            'data-rules': 'integer'
        }));

        myForm.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'requirednumber',
            'data-rules': 'integer|required'
        }));

        var elms = validator.getElements();

        reparse(validator);

        equal(elms.number[0].validate(), true, 'Empty number field is valid');
        equal(elms.requirednumber[0].validate(), false, 'Empty required number field is invalid');

        elms.number[0]._element.value = 'a';
        elms.requirednumber[0]._element.value = '1';

        reparse(validator);

        equal(elms.number[0].validate(), false, 'Sanity check');
        equal(elms.requirednumber[0].validate(), true, 'Sanity check');
    });

    test('(regression) Validation of a matches field fails if it doesn\'t have a [rules] attribute', function () {
        var oldStuff = makeForm();

        var myForm = oldStuff.form;
        var validator = oldStuff.validator;

        myForm.innerHTML = '';

        myForm.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'password'
        }));

        myForm.appendChild(InkElement.create('input', {
            type: 'text',
            name: 'passwordconfirmation',
            'data-rules': 'matches[password]'
        }));

        var elms = validator.getElements();

        reparse(validator);

        equal(elms.passwordconfirmation[0].validate(), true,
            'Empty password matching field is valid because the password is not required');
    });

    test('[disabled] fields count as valid', function() {
        var bag = makeForm();

        InkElement.setHTML(bag.control, '');

        var elm = InkElement.create('input', {
            type: 'text',
            'data-rules': 'required',
            value: ''
        });

        bag.control.appendChild(elm);
        ok(!bag.validator.validate(), 'sanity check');

        elm.setAttribute('disabled', 'disabled');

        ok(bag.validator.validate(), 'now it should be valid');
    });

    test('regression: [disabled] has precedence over forceInvalid when inplace', function() {
        var bag = makeForm();

        InkElement.setHTML(bag.control, '');

        var elm = InkElement.create('input', {
            type: 'text',
            'data-rules': 'required',
            name: 'foo',
            value: ''
        });

        bag.control.appendChild(elm);

        bag.validator.getElements()['foo'][0].forceInvalid('invalid you are!')

        elm.setAttribute('disabled', 'disabled');

        ok(bag.validator.validate(), 'now it should be valid');
    });

    test('Create new FormElements for each control-group in the form', sinon.test(function () {
        var oldStuff = makeForm();

        var myForm = oldStuff.form;
        var validator = oldStuff.validator;

        var initFunc = this.spy(FormValidator.FormElement.prototype, '_init');

        validator.validate();
        equal(initFunc.callCount, 1, 'FormElement#_init called for the existing control-group');

        strictEqual(initFunc.firstCall &&
            initFunc.firstCall.thisValue.getElement(),
            oldStuff.controlGroup,
            'FormElement was called with the correct element as argument');

        var newStuff = makeForm();

        newStuff.form.parentNode.removeChild(newStuff.form);
        newStuff.controlGroup.id = 'element_27';
        myForm.appendChild(newStuff.controlGroup);

        validator.validate();

        equal(initFunc.callCount, 2, 'FormElement#_init called again');

        strictEqual(initFunc.lastCall &&
            initFunc.lastCall.thisValue.getElement(),
            newStuff.controlGroup,
            'FormElement was now called with the new element as argument');

        myForm.parentNode.removeChild(myForm);
    }));

    test('When a form is invalid, _invalid is called with an array of errored elements', sinon.test(function () {
        var oldStuff = makeForm();
        var validator = oldStuff.validator;

        Ink.s('input', oldStuff.form).setAttribute('data-rules', 'required')

        var invalid = this.spy(validator, '_invalid');

        validator.validate();

        equal(invalid.callCount, 1, '_invalid() was called once, because form was invalid')
    }));

    test('_invalid puts a "form-error" class in the form', function () {
        var bag = makeForm()

        bag.validator._invalid();

        ok(Css.hasClassName(bag.form, 'form-error'), 'form-error class added');
    })

    test('extraValidation', function() {
        var extraValidation = sinon.stub();

        var bag = makeForm({
            extraValidation: extraValidation
        });

        extraValidation.returns(true);
        var ret = bag.validator.validate();

        equal(ret, true, 'sanity check: form was valid');

        ok(extraValidation.calledOnce);
        strictEqual(extraValidation.lastCall.thisValue, bag.validator);
        deepEqual(extraValidation.lastCall.args, [{
            'event': undefined,
            validator: bag.validator,
            elements: bag.validator.getElements(),
            errorCount: 0,
        }]);

        extraValidation.returns(false);
        var ret = bag.validator.validate();
        equal(ret, false, 'extraValidation can make a valid form invalid');
    })

    test('setRules', function () {
        var bag = makeForm();

        var elm = bag.validator.getElements()['element_26'][0];
        elm.setRules('foo|bar|baz');
        equal(elm._options.rules, 'foo|bar|baz');
    })

    test('setting data-rules when autoReparse:true should be equivalent to setRules when validate() is called', function () {
        var bag = makeForm({ autoReparse: true });

        var elm = bag.validator.getElements()['element_26'][0];
        elm._element.setAttribute('data-rules', 'foo|bar|baz');
        elm.validate();
        equal(elm._options.rules, 'foo|bar|baz');
    })

    test('removing data-rules should be equivalent to setting element as valid', function () {
        var bag = makeForm({ autoReparse: true })

        bag.form.innerHTML = '<input type="text" name="inpt" data-rules="required" >'

        var elm = bag.validator.getElements()['inpt'][0]
        elm._element.setAttribute('data-rules', 'required')
        ok(!elm.validate(), 'sanity check')
        elm._element.removeAttribute('data-rules')
        ok(elm.validate())
    })

    test('removing element removes it from the getElements result thing.', function () {
        var bag = makeForm()

        bag.form.innerHTML = '<input type="text" name="inpt" data-rules="required" >'

        var elm = bag.validator.getElements()['inpt'][0]

        ok(!bag.validator.validate())

        equal(bag.validator.getElements()['inpt'].length, 1)
        elm._element.parentNode.removeChild(elm._element);
        equal(bag.validator.getElements()['inpt'], undefined)

        ok(bag.validator.validate())
    })

    test('forceInvalid(), unforceInvalid()', function () {
        var bag = makeForm()

        var elm = bag.validator.getElements()['element_26'][0]
        ok(bag.validator.validate(), 'sanity check, form is initially valid')
        elm.forceInvalid('MESSAGE');
        ok(!bag.validator.validate(), 'Not valid any more, because we invalidated an element')
        elm.unforceInvalid();
        ok(bag.validator.validate(), 'Not valid any more, because we invalidated an element')
    })

    test('forceValid(), unforceValid()', function () {
        var bag = makeForm()

        var elm = bag.validator.getElements()['element_26'][0]
        elm.forceInvalid();
        ok(!bag.validator.validate(), 'sanity check, form is initially invalid')
        elm.forceValid();
        ok(bag.validator.validate(), 'Now we\'re valid')
        elm.unforceValid();
        ok(!bag.validator.validate(), 'Not valid any more, because we called unforceValid')
    })
});


text:
using Microsoft.EntityFrameworkCore;
using mvc_ef_demo.Models;

namespace mvc_ef_demo
{
    public class WebsiteDbContext : DbContext
    {
        public WebsiteDbContext(DbContextOptions<WebsiteDbContext> options)
            : base(options)
        {

        }

        public DbSet<Article> Articles { get; set; }
    }
}


text:
import {
  animate,
  state,
  style,
  transition,
  trigger,
  keyframes,
  AnimationTriggerMetadata,
} from '@angular/animations';

/**
 * Animations used by the Material datepicker.
 * @docs-private
 */
export const matDatepickerAnimations: {
  readonly transformPanel: AnimationTriggerMetadata;
  readonly fadeInCalendar: AnimationTriggerMetadata;
} = {
  /** Transforms the height of the datepicker's calendar. */
  transformPanel: trigger('transformPanel', [
    transition('void => enter-dropdown', animate('120ms cubic-bezier(0, 0, 0.2, 1)', keyframes([
      style({opacity: 0, transform: 'scale(1, 0.8)'}),
      style({opacity: 1, transform: 'scale(1, 1)'})
    ]))),
    transition('void => enter-dialog', animate('150ms cubic-bezier(0, 0, 0.2, 1)', keyframes([
      style({opacity: 0, transform: 'scale(0.7)'}),
      style({transform: 'none', opacity: 1})
    ]))),
    transition('* => void', animate('100ms linear', style({opacity: 0})))
  ]),

  /** Fades in the content of the calendar. */
  fadeInCalendar: trigger('fadeInCalendar', [
    state('void', style({opacity: 0})),
    state('enter', style({opacity: 1})),

    // TODO(crisbeto): this animation should be removed since it isn't quite on spec, but we
    // need to keep it until #12440 gets in, otherwise the exit animation will look glitchy.
    transition('void => *', animate('120ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)'))
  ])
};


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <title>extras</title>

    <link href="extras.css" rel="stylesheet" />

                Name:
                <input id="extras-skuNumber" class="textinput" type="text" data-win-bind="value: skuNumber Binding.Mode.twoway" />

                Description:
                <input id="extras-description" class="textinput" type="text" data-win-bind="value: description Binding.Mode.twoway" />

                Unit:
                <input id="extras-unit" class="textinput" type="text" data-win-bind="value: unit Binding.Mode.twoway" />

                Price:
                <input id="extras-unitPrice" class="textinput" type="text" data-win-bind="value: unitPrice Binding.Mode.twoway" />


text:
import Component from "../js/Component";
import Banner from "./Banner";
import Highlights from "./Highlights";

class Home extends Component {
  render() {
    return this.content `
      ${ new Banner() }
      ${ new Highlights() }
    `;
  }
}

export default Home;


text:
from django.conf.urls import url
from . import views

app_name = 'music'

urlpatterns = [
    # /music/
    url(r'^$', views.ImdexView.as_view(), name='index'),

    # /music/<id>/
    url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),

    # /music/album/add
    url(r'album/add/$', views.AlbumCreate.as_view(), name='album-add'),

]


text:
package co.binapp.android.data;

public class StringProcessor {

	public static final String HTTP = "http://";
	public static final String HTTPS = "https://";
	public static final String WWW = "www.";

	public boolean containsLinkCheck(String string) {
		if (string.contains(HTTP) || string.contains(HTTPS) || string.contains(WWW)) {
			return true;
		} else {
			return false;
		}
	}

	public String removeHTTPs(String url) {
		url = url.replace(HTTP, "");
		url = url.replace(HTTPS, "");
		url = url.replace(WWW, "");
		return url;
	}

	public static boolean hasContents(String input) {
		if (!input.equals("") && input != null) {
			return true; // Has contents
		} else {
			return false;
		}
	}

}


text:
[![CI](https://github.com/fredrikaverpil/dotfiles/actions/workflows/test.yml/badge.svg)](https://github.com/fredrikaverpil/dotfiles/actions/workflows/test.yml)

**Introduction**

These are my personal dotfiles, for macOS, Windows and Linux. The setup is based on [dotbot](https://github.com/anishathalye/dotbot) and aims to be as idempotent as possible.

**Table of Contents**

- [macOS](#macos)
  - [Install dotfiles](#install-dotfiles)
  - [Optional installation](#optional-installation)
  - [Configuration](#configuration)
- [Windows 11 + WSL/Ubuntu](#windows-11--wslubuntu)
  - [Windows installations](#windows-installations)
  - [WSL/Ubuntu installations](#wslubuntu-installations)
  - [Configuration](#configuration-1)
    - [Windows Terminal settings](#windows-terminal-settings)
    - [WSL Tray](#wsl-tray)
    - [Set up HHKB for macOS-compatible workflow](#set-up-hhkb-for-macos-compatible-workflow)
  - [Closing notes](#closing-notes)
- [Ubuntu 20.04](#ubuntu-2004)
  - [Prerequisites](#prerequisites)
  - [Install dotfiles](#install-dotfiles-1)
  - [Optional installation](#optional-installation-1)
- [Extras](#extras)
  - [Clone all my public repos](#clone-all-my-public-repos)

## macOS

![image](https://user-images.githubusercontent.com/994357/143506100-fd6a053d-f675-4742-84d8-43df03e48c0a.png)

### Install dotfiles

Install:

```bash
mkdir -p code/repos && cd code/repos
git clone https://github.com/fredrikaverpil/dotfiles.git
cd dotfiles && ./install -vv
```

### Optional installation

Install Xcode commandline tools:

```bash
xcode-select --install
sudo xcodebuild -license accept
```

Install CLI and GUI apps:

```bash
installers/homebrew.sh
installers/zsh.sh
installers/starship.sh
installers/nerdfont.sh
installers/gh.sh
installers/python.sh

brew bundle --file=_macos/Brewfile
brew bundle --file=_macos/Brewfile_mas  # Requires having logged into the App Store
```

### Configuration

Terminal.app settings:

```bash
open _macos/terminal-ocean-dark.terminal
defaults write com.apple.terminal "Default Window Settings" "terminal-ocean-dark"
```

Custom key bindings for Swedish characters in US English layout:

```bash
mkdir ~/Library/KeyBindings/
ln -sf $(pwd)/_macos/DefaultKeyBinding.dict ~/Library/KeyBindings/DefaultKeyBinding.dict
```

Avoid creating .DS_Store files on network or USB volumes:

```bash
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true
```

## Windows 11 + WSL/Ubuntu

This setup aims to run GUIs in Windows with all terminal and coding activities in WSL/Ubuntu.

### Windows installations

  Click here for instructions in older Windows 10

  ```powershell
  # prerequisites
  Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart
  wsl --install
  wsl --list --online

  # reboot!

  # if wsl installed "Ubuntu":
  wsl --terminate Ubuntu
  wsl --unregister Ubuntu

  # install!
  wsl --install --distribution Ubuntu-20.04

  # get winget by downloading "App Installer" from the Microsoft Store:
  # https://www.microsoft.com/en-us/p/app-installer/9nblggh4nns1
  ```

Run from administrative Powershell prompt:

```powershell
# Enable Hyper-V (for WSL)
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart

# Install from ms store
winget install --accept-package-agreements --accept-source-agreements --source msstore "Windows Subsystem for Linux" --id 9P9TQF7MRM4R
winget install --accept-package-agreements --source msstore "Ubuntu 20.04 LTS" --id 9N6SVWS3RX71
```

Start the Ubuntu prompt, create user.

Then install GUI apps (from [Microsoft Store](https://www.microsoft.com/en-us/store/apps/windows) and [winget-pkgs repo](https://github.com/microsoft/winget-pkgs)) in Windows from a Powershell prompt:

```powershell
# Coding
winget install --accept-package-agreements --source msstore "Windows Terminal" --id 9N0DX20HK701
winget install --accept-package-agreements --source msstore "Visual Studio Code" --id XP9KHM4BK9FZ7Q
winget install --accept-package-agreements --source winget "Docker Desktop" --id "Docker.DockerDesktop"
winget install --accept-package-agreements --source msstore "Slack" --id "9WZDNCRDK3WP"
winget install --accept-package-agreements --source winget "Notion" --id "Notion.Notion"

# HHKB/macOS compatible workflow
winget install --accept-package-agreements --source msstore "PureText" --id 9PKJV6319QTL
winget install --accept-package-agreements --source msstore "AutoHotkey Store Edition" --id 9NQ8Q8J78637
winget install --accept-package-agreements --source winget "SharpKeys" --id "RandyRants.SharpKeys"

# Other
winget install --accept-package-agreements --source winget "1Password" --id "AgileBits.1Password"
winget install --accept-package-agreements --source winget "Signal" --id "OpenWhisperSystems.Signal"
winget install --accept-package-agreements --source msstore "Spotify Music" --id 9NCBCSZSJRSB
winget install --accept-package-agreements --source msstore "Microsoft PowerToys" --id XP89DCGQ3K6VLD
```

### WSL/Ubuntu installations

From Ubuntu prompt:

```bash
mkdir -p code/repos && cd code/repos
git clone https://github.com/fredrikaverpil/dotfiles.git
cd dotfiles && ./install -vv
```

### Configuration

#### Windows Terminal settings

* Download and install [Fira Code Nerd font](https://github.com/ryanoasis/nerd-fonts/releases/) in Windows

Run from administrative Powershell prompt:

```powershell
# Remove original settings.json
rm $HOME\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json

# Create symlink into WSL2's dotfiles repo
cd \\wsl.localhost\Ubuntu-20.04\home\fredrik\code\repos\dotfiles
New-Item -ItemType SymbolicLink -Path $HOME\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json -Value _windows\terminal_settings.json
```

#### WSL Tray

* Download [WSL Tray](https://github.com/yzgyyang/wsl-tray/releases)
* Extract in `%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup`

#### Set up [HHKB](https://happyhackingkb.com/) for macOS-compatible workflow

Note: this assumes Autohotkey Sharpkeys and PureText are already installed.

* Install `autohotkey.ahk` by running this from a Powershell prompt:

```powershell
cp \\wsl.localhost\Ubuntu-20.04\home\fredrik\code\repos\dotfiles\_windows\autohotkey.ahk "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\autohotkey.ahk"
```

  Click here to see symlinking instructions

  Symlinking can be done, instead of copying the `autohotkey.ahk`, from an administrative Powershell prompt:

  ```powershell
  New-Item -ItemType SymbolicLink -Path "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\autohotkey.ahk" -Value _windows\autohotkey.ahk
  ```

  :warning: ...however, if WSL is not running, the AutoHotkey script won't run. It may be more desireable to copy the file into place.

* To override Win (Left) + l, launch Sharpkeys, load the `\\wsl.localhost\Ubuntu-20.04\home\fredrik\code\repos\dotfiles\_windows\sharpkeys.skl` file and write changes to the Registry.
* In PureText, remap (Ctrl + Shift + v) to enable pasting of text without formatting.

### Closing notes

Reboot machine.

Proceed with reading more on the Ubuntu setup to install zsh, Python etc.

## Ubuntu 20.04

### Prerequisites

```bash
sudo apt update
sudo add-apt-repository universe
sudo apt upgrade
sudo apt install git curl unzip bash-completion
```

### Install dotfiles

```bash
mkdir -p code/repos && cd code/repos
git clone https://github.com/fredrikaverpil/dotfiles.git
cd dotfiles && ./install -vv
```

### Optional installation

```bash
installers/starship.sh
installers/nerdfont.sh
installers/zsh.sh  # remove the default prompt from ~/.zshrc after installation
installers/gh.sh
installers/python.sh
installers/docker.sh  # only if Docker Desktop in Windows was not installed
installers/snap-apps.sh
installers/nix.sh
```

## Extras

### Clone all my public repos

If more than 100 repos, change `PAGE` variable..

```bash
cd ~/code/repos
USER=fredrikaverpil; PAGE=1; curl "https://api.github.com/users/$USER/repos?page=$PAGE&per_page=100" | grep -e 'git_url*' | cut -d \" -f 4 | xargs -L1 git clone --recursive
```


text:
<?php
if ($judge['value'] != "Lockdown" || (isset($_SESSION['loggedin']) && $_SESSION['team']['status'] == 'Admin')) {
    if (isset($_GET['code'])) {
        $_GET['code'] = addslashes($_GET['code']);
        if (isset($_SESSION['loggedin']) && $_SESSION['team']['status'] == "Admin") {
            $query = "select * from problems where code = '$_GET[code]'";
            echo " Edit";
        } else {
            $query = "select * from problems where code = '$_GET[code]' and status != 'Deleted'";
        }
        $result = DB::findOneFromQuery($query);
        if ($result == NULL) {
            echo "

Problem not Found :(
The problem you are looking for doesn't exsits.

";
        } else {
            if ($result['contest'] == 'contest' && ( (!isset($_SESSION['loggedin'])) || ($_SESSION['team']['status'] != 'Admin'))) {
                $query = "select starttime from contest where code = '$result[pgroup]'";
                $check = DB::findOneFromQuery($query);
                if ($check['starttime'] > time()) {
                    echo "

Problem not Found. :(
The problem you are looking for doesn't exsits.

";
                    $flag = 1;
                } else {
                    $flag = 0;
                }
            } else {
                $flag = 0;
            }
            if ($flag == 0) {
                $statement = stripslashes($result["statement"]);
                $statement = preg_replace("/\n/", "
", $statement);
                $statement = preg_replace("/<image \/>/", "", $statement);
                echo "
$result[name]

" . ((isset($_SESSION['loggedin'])) ? ("My Submissions") : ("")) . "All Submissions" . (($result['status'] == 'Active' || (isset($_SESSION['loggedin']) && $_SESSION['team']['status'] == "Admin")) ? ("Submit") : ('')) . "

" . $statement . "

                Time Limit : $result[timelimit] Second(s)
Score : $result[score] Point(s)
Input File Limit : $result[maxfilesize] Bytes
Languages Allowed : $result[languages]";
                echo "

Clarifications
";
                $query = "select * from clar where pid = $result[pid] and access = 'Public'";
                $clar = DB::findAllFromQuery($query);
                if ($clar != NULL) {
                    foreach ($clar as $row) {
                        $query = "select teamname from teams where tid = $row[tid]";
                        $team = DB::findOneFromQuery($query);
                        $rowquery = eregi_replace("\n", "
",htmlspecialchars($row['query']));
                        $rowreply = eregi_replace("\n", "
", htmlspecialchars($row['reply']));
                        echo "$team[teamname]:
Q. $rowquery
" . (($rowreply != "") ? ("A. $rowreply
") : ('')) . "
";
                        if (isset($_SESSION['loggedin']) && $_SESSION['team']['status'] == 'Admin') {
                            echo "<form role='form' method='post' action='" . SITE_URL . "/process.php'>";
                            echo "Access: <select style='width: 250px;' class='form-control' name='access'><option value='public' " . (($row['access'] == "public") ? ("selected='selected' ") : ("")) . ">Public</option><option value='deleted' " . (($row['access'] == "deleted") ? ("selected='selected' ") : ("")) . ">Deleted</option></select>
";
                            echo "<input type='hidden' name='tid' value='$row[tid]' /><input type='hidden' name='pid' value='$row[pid]' /><input type='hidden' name='time' value='$row[time]' />
<textarea class='form-control' name='reply' style='width: 450px; height: 100px;'>$row[reply]</textarea>

<input type='submit' class='btn btn-primary' name='clarreply' value='Reply / Change Reply'/>
</form>";
                        }
                    }
                }
                else
                    echo "No Clarifications.
";
                if (isset($_SESSION['loggedin'])) {
                    ?>

Post Clarification

                    <form action="<?php echo SITE_URL; ?>/process.php" role='form' method="post">
                        <input type="hidden" value="<?php echo $result['pid']; ?>" name="pid" />
                        <textarea class='form-control' style="width: 500px; height: 200px;" name="query"></textarea>

                        <input name="clar" type="submit" class="btn btn-primary" />
                    </form>

                    <?php
                }
            }
        }
    } else {
        echo "
Practice Problems
";
        if (isset($_SESSION['loggedin'])){
            $solved = array();
            $query = "select distinct(pid) as pid from runs where result = 'AC' and tid = ".$_SESSION['team']['id'];
            $res = DB::findAllFromQuery($query);
            foreach($res as $row){
                $solved[$row['pid']] = true;
            }
        }
        if (isset($_SESSION['loggedin']) && $_SESSION['team']['status'] == "Admin") {
            $query = "select pid, name, code, status, pgroup, type, score, solved, total from problems where contest='practice' order by pid desc";
        } else {
            $query = "select pid, name, code, status, pgroup, type, score, solved, total from problems where status != 'Deleted' and contest='practice' order by pid desc";
        }
        $res = DB::findAllFromQuery($query);
        $lastgroup = "";
        echo "
";
        foreach ($res as $row) {
            if ($row['pgroup'] != $lastgroup){
                echo "

$row[pgroup]

Name	Score	Type	Code	Submissions
";
                $lastgroup = $row['pgroup'];
            }
            echo "
$row[name]	$row[score]	$row[type]	$row[code]	$row[solved]/$row[total]
";
        }
        echo "
";
    }
} else {
    echo "

Lockdown Mode :(
This feature is now offline as Judge is in Lockdown mode.

";
}
?>


text:
namespace GiftBox.Data.Models
{
    using System;
    using GiftBox.Data.Common.Models;

    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;

    public class Gift : AuditInfo, IDeletableEntity
    {
        public int Id { get; set; }

        [Required]
        [MaxLength(100)]
        public string AditionalInfo { get; set; }

        public DateTime ExpirationDate { get; set; }

        public string ImageUrl { get; set; }

        public bool IsFulfilled { get; set; }

        public bool Claimed { get; set; }

        public string ClaimedById { get; set; }

        public virtual User ClaimedBy { get; set; }

        public int ChildId { get; set; }

        public virtual Child Child { get; set; }

        public int EventCategoryId { get; set; }

        public virtual EventCategory EventCategory { get; set; }

        public bool IsDeleted { get; set; }

        public DateTime? DeletedOn { get; set; }
    }
}


text:
package test_test

import (
	"testing"
	"github.com/Rubentxu/lbricks/bgo"

)

type TestNode struct {
	bgo.BaseNode
	statusResponse  bgo.Status
}

func (this *TestNode) Tick(context *bgo.Context) bgo.Status {
	memory := context.GetContextMemory()
	var statusResponses []string = memory.ArrayString["StatusResponses"]
	statusResponses = append(statusResponses,string(this.statusResponse))
	memory.ArrayString["StatusResponses"] = statusResponses
	return this.statusResponse
}

func NewTestNode(title string, statusResponse bgo.Status) *TestNode {
	node := &TestNode{}
	node.ID = bgo.CreateUUID()
	node.Category = bgo.ACTION
	node.Name = "TestNode"
	node.Title = title
	node.statusResponse = statusResponse
	return node
}

func ArrayEquals(a []string, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}

func TestSequenceRoot(t *testing.T) {
	blackboard :=  bgo.CreateBlackboard()
	tree := bgo.CreateBehaviorTree("Pruebas", "Test", blackboard)
	context := bgo.CreateContext("")

	tree.Root  = bgo.NewSequence("SequenceTest",
								bgo.NewPriority("PriorityTest",
												NewTestNode("Nodo1",bgo.FAILURE),
												NewTestNode("Nodo2",bgo.SUCCESS),
												NewTestNode("Nodo3",bgo.SUCCESS)),

								NewTestNode("Nodo4",bgo.SUCCESS),
								NewTestNode("Nodo5",bgo.SUCCESS))

	tree.Tick(context)
	elem ,_ := context.GetContextMemory().ArrayString["StatusResponses"]
	expected := []string { "Failure","Success","Success","Success" }

	if !ArrayEquals(expected,elem) {
		t.Errorf("Error StatusResponses no son iguales a lo experado %s <---> %s", expected,elem)
	} else {
		t.Logf("Final status %s \r",elem)
	}

}

func TestNSequenceRoot(t *testing.T) {
	blackboard :=  bgo.CreateBlackboard()
	tree := bgo.CreateBehaviorTree("Pruebas", "Test", blackboard)
	context := bgo.CreateContext("context1")
	context2 := bgo.CreateContext("context1")
	context3 := bgo.CreateContext("context1")

	tree.Root  = bgo.NewSequence("SequenceTest",
		bgo.NewPriority("PriorityTest",
			NewTestNode("Nodo1",bgo.FAILURE),
			NewTestNode("Nodo2",bgo.SUCCESS),
			NewTestNode("Nodo3",bgo.SUCCESS)),

		NewTestNode("Nodo4",bgo.SUCCESS),
		NewTestNode("Nodo5",bgo.SUCCESS))

	tree.Tick(context)
	tree.Tick(context2)
	tree.Tick(context3)

	elem ,_ := context.GetContextMemory().ArrayString["StatusResponses"]
	elem2 ,_ := context2.GetContextMemory().ArrayString["StatusResponses"]
	elem3 ,_ := context3.GetContextMemory().ArrayString["StatusResponses"]
	expected := []string { "Failure","Success","Success","Success" }

	if !ArrayEquals(expected,elem) && !ArrayEquals(expected,elem2) && !ArrayEquals(expected,elem3){
		t.Errorf("Error StatusResponses no son iguales a lo experado %s <--->%s -- %s -- %s \r",
			expected,elem, elem2, elem3)
	} else {
		t.Logf("Final status %s -- %s -- %s \r",elem, elem2, elem3)
	}

}

func TestPriorityRoot(t *testing.T) {
	blackboard :=  bgo.CreateBlackboard()
	tree := bgo.CreateBehaviorTree("Pruebas2", "Test2", blackboard)
	context := bgo.CreateContext("")

	tree.Root  =	bgo.NewPriority("PriorityTest",
									bgo.NewSequence("SequenceTestA",
												NewTestNode("NodoA",bgo.SUCCESS),
												NewTestNode("NodoB",bgo.FAILURE),
												NewTestNode("NodoC",bgo.SUCCESS)),
									bgo.NewSequence("SequenceTestB",
													NewTestNode("NodoD",bgo.SUCCESS),
													NewTestNode("NodoE",bgo.SUCCESS)),
									)

	tree.Tick(context)

	elem ,_ := context.GetContextMemory().ArrayString["StatusResponses"]
	expected := []string { "Success","Failure","Success","Success" }

	if !ArrayEquals(expected,elem) {
		t.Errorf("Error StatusResponses no son iguales a lo experado %s <---> %s", expected,elem)
	} else {
		t.Logf("Final status %s \r",elem)
	}

}

func TestNPriorityRoot(t *testing.T) {
	blackboard :=  bgo.CreateBlackboard()
	tree := bgo.CreateBehaviorTree("Pruebas2", "Test2", blackboard)
	context := bgo.CreateContext("context1")
	context2 := bgo.CreateContext("context1")
	context3 := bgo.CreateContext("context1")

	tree.Root  =	bgo.NewPriority("PriorityTest",
		bgo.NewSequence("SequenceTestA",
			NewTestNode("NodoA",bgo.SUCCESS),
			NewTestNode("NodoB",bgo.FAILURE),
			NewTestNode("NodoC",bgo.SUCCESS)),
		bgo.NewSequence("SequenceTestB",
			NewTestNode("NodoD",bgo.SUCCESS),
			NewTestNode("NodoE",bgo.SUCCESS)),
	)

	tree.Tick(context)
	tree.Tick(context2)
	tree.Tick(context3)

	elem ,_ := context.GetContextMemory().ArrayString["StatusResponses"]
	elem2 ,_ := context2.GetContextMemory().ArrayString["StatusResponses"]
	elem3 ,_ := context3.GetContextMemory().ArrayString["StatusResponses"]

	expected := []string { "Success","Failure","Success","Success" }

	if !ArrayEquals(expected,elem) && !ArrayEquals(expected,elem2) && !ArrayEquals(expected,elem3){
		t.Errorf("Error StatusResponses no son iguales a lo experado %s <--->%s -- %s -- %s \r",
			expected,elem, elem2, elem3)
	} else {
		t.Logf("Final status %s -- %s -- %s \r",elem, elem2, elem3)
	}

}


text:
package com.autodesk.spark.sdk.models.Request;

import com.google.gson.Gson;

/**
 * Created by ronnyremsnik on 3/2/15.
 */
public class AssetRequest {

    public String asset_id;

    public String asset_name;
    public String asset_description;
    public String asset_tags;

    public AssetRequest(String asset_id) {
        this.asset_id = asset_id;
    }

    public AssetRequest(String assetName, String assetDescription, String assetTags)
    {
        this.asset_name = assetName;
        this.asset_description = assetDescription;
        this.asset_tags = assetTags;
    }

    public String toJson() {
        Gson gson = new Gson();
        return gson.toJson(this, AssetRequest.class);

    }

}


text:
* http://github.com/rails/arel

## DESCRIPTION

Arel is a SQL AST manager for Ruby. It

1. Simplifies the generation of complex SQL queries
2. Adapts to various RDBMS systems

It is intended to be a framework framework; that is, you can build your own ORM
with it, focusing on innovative object and collection modeling as opposed to
database compatibility and query generation.

## Status

For the moment, Arel uses Active Record's connection adapters to connect to the various engines, connection pooling, perform quoting, and do type conversion.

## A Gentle Introduction

Generating a query with Arel is simple. For example, in order to produce

```sql
SELECT * FROM users
```

you construct a table relation and convert it to sql:

```ruby
users = Arel::Table.new(:users)
query = users.project(Arel.sql('*'))
query.to_sql
```

### More Sophisticated Queries

Here is a whirlwind tour through the most common relational operators. These will probably cover 80% of all interaction with the database.

First is the 'restriction' operator, `where`:

```ruby
users.where(users[:name].eq('amy'))
# => SELECT * FROM users WHERE users.name = 'amy'
```

What would, in SQL, be part of the `SELECT` clause is called in Arel a `projection`:

```ruby
users.project(users[:id])
# => SELECT users.id FROM users
```

Joins resemble SQL strongly:

```ruby
users.join(photos).on(users[:id].eq(photos[:user_id]))
# => SELECT * FROM users INNER JOIN photos ON users.id = photos.user_id
```

What are called `LIMIT` and `OFFSET` in SQL are called `take` and `skip` in Arel:

```ruby
users.take(5) # => SELECT * FROM users LIMIT 5
users.skip(4) # => SELECT * FROM users OFFSET 4
```

`GROUP BY` is called `group`:

```ruby
users.project(users[:name]).group(users[:name])
# => SELECT users.name FROM users GROUP BY users.name
```

The best property of the Relational Algebra is its "composability", or closure under all operations. For example, to restrict AND project, just "chain" the method invocations:

```ruby
users                                 \
  .where(users[:name].eq('amy'))      \
  .project(users[:id])                \
# => SELECT users.id FROM users WHERE users.name = 'amy'
```

All operators are chainable in this way, and they are chainable any number of times, in any order.

```ruby
users.where(users[:name].eq('bob')).where(users[:age].lt(25))
```

Of course, many of the operators take multiple arguments, so the last example can be written more tersely:

```ruby
users.where(users[:name].eq('bob'), users[:age].lt(25))
```

The `OR` operator works like this:

```ruby
users.where(users[:name].eq('bob').or(users[:age].lt(25)))
```

The `AND` operator behaves similarly.

### The Crazy Features

The examples above are fairly simple and other libraries match or come close to matching the expressiveness of Arel (e.g., `Sequel` in Ruby).

#### Inline math operations

Suppose we have a table `products` with prices in different currencies. And we have a table `currency_rates`, of constantly changing currency rates. In Arel:

```ruby
products = Arel::Table.new(:products)
products.columns
# => [products[:id], products[:name], products[:price], products[:currency_id]]

currency_rates = Arel::Table.new(:currency_rates)
currency_rates.columns
# => [currency_rates[:from_id], currency_rates[:to_id], currency_rates[:date], currency_rates[:rate]]
```

Now, to order products by price in user preferred currency simply call:

```ruby
products.
  join(:currency_rates).on(products[:currency_id].eq(currency_rates[:from_id])).
  where(currency_rates[:to_id].eq(user_preferred_currency), currency_rates[:date].eq(Date.today)).
  order(products[:price] * currency_rates[:rate])
```

#### Complex Joins

Where Arel really shines in its ability to handle complex joins and aggregations. As a first example, let's consider an "adjacency list", a tree represented in a table. Suppose we have a table `comments`, representing a threaded discussion:

```ruby
comments = Arel::Table.new(:comments)
```

And this table has the following attributes:

```ruby
comments.columns
# => [comments[:id], comments[:body], comments[:parent_id]]
```

The `parent_id` column is a foreign key from the `comments` table to itself. Now, joining a table to itself requires aliasing in SQL. In fact, you may alias in Arel as well:

```ruby
replies = comments.alias
comments_with_replies = \
  comments.join(replies).on(replies[:parent_id].eq(comments[:id]))
# => SELECT * FROM comments INNER JOIN comments AS comments_2 WHERE comments_2.parent_id = comments.id
```

This will return the first comment's reply's body.

### License

Arel is released under the [MIT License](http://opensource.org/licenses/MIT).


text:
<?php

namespace Forms\Constraints;

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD", "ANNOTATION"})
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanOrEqual extends AbstractComparison
{
    public $message = 'This value should be greater than or equal to {{ compared_value }}.';
}


text:
class CalendarsController < ApplicationController
  def show
    event = Event.find_by_uuid!(params[:id])
    ics_event = Calendar.generate(event)

    send_data(ics_event, filename: 'calendar.ics')
  end
end


text:
[jvm]
Content
val [Method](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html).[parameterNames](parameter-names.md): [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)<[String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)>
More info

Gets parameter names of receiver [Method](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html).

[jvm]
Content
val <[T](parameter-names.md) : [Any](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)> [Constructor](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Constructor.html)<[T](parameter-names.md)>.[parameterNames](parameter-names.md): [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)<[String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)>
More info

Gets parameter names of receiver [Constructor](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Constructor.html).


text:
tsc lib/js/View.ts --out com/js --module AMD --target ES5
tsc node/app.ts


text:
// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.cloudera.csd.validation.monitoring.constraints;

import com.cloudera.csd.validation.references.DescriptorPath;
import com.cloudera.csd.validation.references.DescriptorPath.BeanDescriptorNode;
import com.cloudera.csd.validation.references.DescriptorPath.DescriptorNode;

import com.google.common.base.Objects;

import java.io.Serializable;
import java.lang.annotation.ElementType;

import javax.validation.ConstraintViolation;
import javax.validation.ElementKind;
import javax.validation.Path;
import javax.validation.metadata.ConstraintDescriptor;

/**
 * An implementation of the ConstraintViolation interface. This allows the
 * monitoring violation to look and feel like violation produced by the
 * hibernate validator.
 *
 * @param <T> The root object type.
 */
public class MonitoringConstraintViolation<T> implements ConstraintViolation<T>,
    Serializable {

  /**
   * Build a ReferenceConstraintViolation from a reference violaiton.
   */
  public static <T> MonitoringConstraintViolation<T> forViolation(
      String message,
      Object currentBean,
      Object currentValue,
      DescriptorPath path) {

    DescriptorNode first = path.getTailNode();
    T rootBean = (T)first.as(BeanDescriptorNode.class).getBean();
    Class<T> rootBeanClass = (Class<T>)rootBean.getClass();

    return new MonitoringConstraintViolation<T>(
      message,
      message,
      rootBeanClass,
      rootBean,
      currentBean,
      currentValue,
      path,
      null,
      ElementType.TYPE,
      null,
      null
    );
  }

  private final String interpolatedMessage;
  private final T rootBean;
  private final Object value;
  private final DescriptorPath propertyPath;
  private final Object leafBeanInstance;
  private final ConstraintDescriptor<?> constraintDescriptor;
  private final String messageTemplate;
  private final Class<T> rootBeanClass;
  private final ElementType elementType;
  private final Object[] executableParameters;
  private final Object executableReturnValue;

  public MonitoringConstraintViolation(
      String messageTemplate,
      String interpolatedMessage,
      Class<T> rootBeanClass,
      T rootBean,
      Object leafBeanInstance,
      Object value,
      DescriptorPath propertyPath,
      ConstraintDescriptor<?> constraintDescriptor,
      ElementType elementType,
      Object[] executableParameters,
      Object executableReturnValue) {
    this.messageTemplate = messageTemplate;
    this.interpolatedMessage = interpolatedMessage;
    this.rootBean = rootBean;
    this.value = value;
    this.propertyPath = propertyPath;
    this.leafBeanInstance = leafBeanInstance;
    this.constraintDescriptor = constraintDescriptor;
    this.rootBeanClass = rootBeanClass;
    this.elementType = elementType;
    this.executableParameters = executableParameters;
    this.executableReturnValue = executableReturnValue;
  }

  @Override
  public String getMessage() {
    return interpolatedMessage;
  }

  @Override
  public String getMessageTemplate() {
    return messageTemplate;
  }

  @Override
  public T getRootBean() {
    return rootBean;
  }

  @Override
  public Class<T> getRootBeanClass() {
    return rootBeanClass;
  }

  @Override
  public Object getLeafBean() {
    return leafBeanInstance;
  }

  @Override
  public Object getInvalidValue() {
    return value;
  }

  @Override
  public Path getPropertyPath() {
    return propertyPath;
  }

  @Override
  public ConstraintDescriptor<?> getConstraintDescriptor() {
    return constraintDescriptor;
  }

  @Override
  public <C> C unwrap(Class<C> type) {
    if (type.isAssignableFrom(ConstraintViolation.class)) {
      return type.cast(this);
    }
    throw new UnsupportedOperationException("Type " + type + " not supported for unwrapping.");
  }

  @Override
  public Object[] getExecutableParameters() {
    return executableParameters;
  }

  @Override
  public Object getExecutableReturnValue() {
    return executableReturnValue;
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof MonitoringConstraintViolation<?>)) {
      return false;
    }
    MonitoringConstraintViolation<?> that = (MonitoringConstraintViolation<?>) o;
    return Objects.equal(this.interpolatedMessage, that.interpolatedMessage) &&
           Objects.equal(this.rootBean, that.rootBean) &&
           Objects.equal(this.value, that.value) &&
           Objects.equal(this.propertyPath, that.propertyPath) &&
           Objects.equal(this.leafBeanInstance, that.leafBeanInstance) &&
           Objects.equal(this.constraintDescriptor, that.constraintDescriptor) &&
           Objects.equal(this.messageTemplate, that.messageTemplate) &&
           Objects.equal(this.rootBeanClass, that.rootBeanClass) &&
           Objects.equal(this.elementType, that.elementType) &&
           Objects.equal(this.executableParameters, that.executableParameters) &&
           Objects.equal(this.executableReturnValue, that.executableReturnValue);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(interpolatedMessage,
                            rootBean,
                            value,
                            propertyPath,
                            leafBeanInstance,
                            constraintDescriptor,
                            messageTemplate,
                            rootBeanClass,
                            elementType,
                            executableParameters,
                            executableReturnValue);
  }

  @Override
  public String toString() {
    return Objects.toStringHelper(this)
                  .omitNullValues()
                  .add("interpolatedMessage", interpolatedMessage)
                  .add("rootBean", rootBean)
                  .add("value", value)
                  .add("propertyPath", propertyPath)
                  .add("leafBeanInstance", leafBeanInstance)
                  .add("constraintDescriptor", constraintDescriptor)
                  .add("messageTemplate", messageTemplate)
                  .add("rootBeanClass", rootBeanClass)
                  .add("elementType", elementType)
                  .add("executableParameters", executableParameters)
                  .add("executableReturnValue", executableReturnValue)
                  .toString();
  }

}


text:
<?php

class ClerkLogger extends ModuleAdminController
{
    private $Platform;
    private $Key;
    private $Date;
    private $Time;
    /**
     * @var int
     */
    private $language_id;

    /**
     * @var int
     */
    private $shop_id;

    /**
     * ClerkLogger constructor.
     * @throws Exception
     */
    function __construct()
    {

        $context = Context::getContext();

        //Set shop id
        $this->shop_id = (Tools::getValue('clerk_shop_select')) ? (int)Tools::getValue('clerk_shop_select') : $context->shop->id;

        //Set language id
        $this->language_id = (Tools::getValue('clerk_language_select')) ? (int)Tools::getValue('clerk_language_select') : $context->language->id;
        $this->Platform = 'Prestashop';
        $this->Key = Configuration::get('CLERK_PUBLIC_KEY', $this->language_id, null, $this->shop_id);
        $this->Date = new DateTime();
        $this->Time = $this->Date->getTimestamp();

    }

    /**
     * @param $Message
     * @param $Metadata
     */
    public function log($Message, $Metadata)
    {
        header('User-Agent: ClerkExtensionBot Prestashop/v' ._PS_VERSION_. ' Clerk/v'.Module::getInstanceByName('clerk')->version. ' PHP/v'.phpversion());
        if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')

            $Metadata['uri'] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

        else {

            $Metadata['uri'] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

        }

        if ($_GET) {

            $Metadata['params'] = $_GET;

        }elseif ($_POST) {

            $Metadata['params'] = $_POST;

        }

        $Type = 'log';

        if (Configuration::get('CLERK_LOGGING_ENABLED', $this->language_id, null, $this->shop_id) !== '1') {

        } else {

            if (Configuration::get('CLERK_LOGGING_LEVEL', $this->language_id, null, $this->shop_id) !== 'all') {

            } else {

                if (Configuration::get('CLERK_LOGGING_TO', $this->language_id, null, $this->shop_id) == 'collect') {

                    $Endpoint = 'http://api.clerk.io/v2/log/debug';

                    $data_string = json_encode([
                        'key' =>$this->Key,
                        'source' => $this->Platform,
                        'time' => $this->Time,
                        'type' => $Type,
                        'message' => $Message,
                        'metadata' => $Metadata]);

                    $curl = curl_init();

                    curl_setopt($curl, CURLOPT_URL, $Endpoint);
                    curl_setopt($curl, CURLOPT_POST, true);
                    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);

                    $response = json_decode(curl_exec($curl));

                    if ($response->status == 'error') {

                        $this->LogToFile($Message,$Metadata);

                    }

                    curl_close($curl);

                } elseif (Configuration::get('CLERK_LOGGING_TO', $this->language_id, null, $this->shop_id) == 'file') {

                    $this->LogToFile($Message, $Metadata);

                }
            }
        }
    }

    /**
     * @param $Message
     * @param $Metadata
     */
    public function error($Message, $Metadata)
    {
        header('User-Agent: ClerkExtensionBot Prestashop/v' ._PS_VERSION_. ' Clerk/v'.Module::getInstanceByName('clerk')->version. ' PHP/v'.phpversion());
        if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')

            $Metadata['uri'] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

        else {

            $Metadata['uri'] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

        }

        if ($_GET) {

            $Metadata['params'] = $_GET;

        }elseif ($_POST) {

            $Metadata['params'] = $_POST;

        }

        $Type = 'error';

        if (Configuration::get('CLERK_LOGGING_ENABLED', $this->language_id, null, $this->shop_id) !== '1') {

        } else {

            if (Configuration::get('CLERK_LOGGING_TO', $this->language_id, null, $this->shop_id) == 'collect') {

                $Endpoint = 'http://api.clerk.io/v2/log/debug';

                $data_string = json_encode([
                    'debug' => '1',
                    'key' =>$this->Key,
                    'source' => $this->Platform,
                    'time' => $this->Time,
                    'type' => $Type,
                    'message' => $Message,
                    'metadata' => $Metadata]);

                $curl = curl_init();

                curl_setopt($curl, CURLOPT_URL, $Endpoint);
                curl_setopt($curl, CURLOPT_POST, true);
                curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);

                $response = json_decode(curl_exec($curl));

                if ($response->status == 'error') {

                    $this->LogToFile($Message,$Metadata);

                }

                curl_close($curl);

            } elseif (Configuration::get('CLERK_LOGGING_TO', $this->language_id, null, $this->shop_id) == 'file') {

                $this->LogToFile($Message, $Metadata);

            }
        }
    }

    /**
     * @param $Message
     * @param $Metadata
     */
    public function warn($Message, $Metadata)
    {
        header('User-Agent: ClerkExtensionBot Prestashop/v' ._PS_VERSION_. ' Clerk/v'.Module::getInstanceByName('clerk')->version. ' PHP/v'.phpversion());
        if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')

            $Metadata['uri'] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

        else {

            $Metadata['uri'] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

        }

        if ($_GET) {

            $Metadata['params'] = $_GET;

        }elseif ($_POST) {

            $Metadata['params'] = $_POST;

        }

        $Type = 'warn';

        if (Configuration::get('CLERK_LOGGING_ENABLED', $this->language_id, null, $this->shop_id) !== '1') {

        } else {

            if (Configuration::get('CLERK_LOGGING_LEVEL', $this->language_id, null, $this->shop_id) == 'error') {

            } else {

                if (Configuration::get('CLERK_LOGGING_TO', $this->language_id, null, $this->shop_id) == 'collect') {

                    $Endpoint = 'http://api.clerk.io/v2/log/debug';

                    $data_string = json_encode([
                        'debug' => '1',
                        'key' =>$this->Key,
                        'source' => $this->Platform,
                        'time' => $this->Time,
                        'type' => $Type,
                        'message' => $Message,
                        'metadata' => $Metadata]);

                    $curl = curl_init();

                    curl_setopt($curl, CURLOPT_URL, $Endpoint);
                    curl_setopt($curl, CURLOPT_POST, true);
                    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);

                    $response = json_decode(curl_exec($curl));

                    if ($response->status == 'error') {

                        $this->LogToFile($Message,$Metadata);

                    }

                    curl_close($curl);

                } elseif (Configuration::get('CLERK_LOGGING_TO', $this->language_id, null, $this->shop_id) == 'file') {

                    $this->LogToFile($Message, $Metadata);

                }
            }
        }
    }

    public function LogToFile($Message,$Metadata)
    {

        $log = $this->Date->format('Y-m-d H:i:s') . ' MESSAGE: ' . $Message . ' METADATA: ' . json_encode($Metadata) . PHP_EOL .
            '-------------------------' . PHP_EOL;
        $path = _PS_MODULE_DIR_ . '/clerk/clerk_log.log';

        fopen($path, "a+");
        file_put_contents($path, $log, FILE_APPEND);

    }

}


text:
package apps::microsoft::hyperv::2012::local::mode::nodeintegrationservice;

use base qw(centreon::plugins::templates::counter);

use strict;
use warnings;
use centreon::plugins::misc;
use centreon::common::powershell::hyperv::2012::nodeintegrationservice;
use apps::microsoft::hyperv::2012::local::mode::resources::types qw($node_vm_state $node_vm_integration_service_operational_status);
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
use JSON::XS;

sub custom_service_status_output {
    my ($self, %options) = @_;

    return 'status: ' . $self->{result_values}->{primary_status} . '/' . $self->{result_values}->{secondary_status};
}

sub custom_global_status_output {
    my ($self, %options) = @_;

    return 'state/version: ' . $self->{result_values}->{integration_service_state} . '/' . $self->{result_values}->{integration_service_version};
}

sub set_counters {
    my ($self, %options) = @_;

    $self->{maps_counters_type} = [
        { name => 'vm', type => 2, cb_prefix_output => 'prefix_vm_output', cb_long_output => 'vm_long_output', message_multiple => 'All integration services are ok',
          group => [ { name => 'global', cb_prefix_output => 'prefix_global_output' }, { name => 'service', cb_prefix_output => 'prefix_service_output' } ]
        }
    ];

    $self->{maps_counters}->{global} = [
        { label => 'global-status', threshold => 0, set => {
                key_values => [ { name => 'integration_service_state' }, { name => 'integration_service_version' }, { name => 'state' }, { name => 'vm' } ],
                closure_custom_output => $self->can('custom_global_status_output'),
                closure_custom_perfdata => sub { return 0; },
                closure_custom_threshold_check => \&catalog_status_threshold
            }
        }
    ];

    $self->{maps_counters}->{service} = [
        { label => 'service-status', threshold => 0, set => {
                key_values => [ { name => 'primary_status' }, { name => 'secondary_status' }, { name => 'enabled' }, { name => 'vm' }, { name => 'service' } ],
                closure_custom_output => $self->can('custom_service_status_output'),
                closure_custom_perfdata => sub { return 0; },
                closure_custom_threshold_check => \&catalog_status_threshold
            }
        }
    ];
}

sub vm_long_output {
    my ($self, %options) = @_;

    return "checking virtual machine '" . $options{instance_value}->{vm} . "'";
}

sub prefix_vm_output {
    my ($self, %options) = @_;

    return "VM '" . $options{instance_value}->{vm} . "' ";
}

sub prefix_service_output {
    my ($self, %options) = @_;

    return "integration service '" . $options{instance_value}->{service} . "' ";
}

sub prefix_global_output {
    my ($self, %options) = @_;

    return "global virtual machine '" . $options{instance_value}->{vm} . "' integration service ";
}

sub new {
    my ($class, %options) = @_;
    my $self = $class->SUPER::new(package => __PACKAGE__, %options);
    bless $self, $class;

    $options{options}->add_options(arguments => {
        'timeout:s'           => { name => 'timeout', default => 50 },
        'command:s'           => { name => 'command', default => 'powershell.exe' },
        'command-path:s'      => { name => 'command_path' },
        'command-options:s'   => { name => 'command_options', default => '-InputFormat none -NoLogo -EncodedCommand' },
        'no-ps'               => { name => 'no_ps' },
        'ps-exec-only'        => { name => 'ps_exec_only' },
        'ps-display'          => { name => 'ps_display' },
        'filter-vm:s'         => { name => 'filter_vm' },
        'filter-note:s'       => { name => 'filter_note' },
        'filter-status:s'     => { name => 'filter_status', default => 'running' },
        'warning-global-status:s'   => { name => 'warning_global_status', default => '%{integration_service_state} =~ /Update required/i' },
        'critical-global-status:s'  => { name => 'critical_global_status', default => '' },
        'warning-service-status:s'  => { name => 'warning_service_status', default => '' },
        'critical-service-status:s' => { name => 'critical_service_status', default => '%{primary_status} !~ /Ok/i' }
    });

    return $self;
}

sub check_options {
    my ($self, %options) = @_;
    $self->SUPER::check_options(%options);

    $self->change_macros(macros => ['warning_service_status', 'critical_service_status', 'warning_global_status', 'critical_global_status']);
}

sub manage_selection {
    my ($self, %options) = @_;

    if (!defined($self->{option_results}->{no_ps})) {
        my $ps = centreon::common::powershell::hyperv::2012::nodeintegrationservice::get_powershell();
        if (defined($self->{option_results}->{ps_display})) {
            $self->{output}->output_add(
                severity => 'OK',
                short_msg => $ps
            );
            $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
            $self->{output}->exit();
        }

        $self->{option_results}->{command_options} .= " " . centreon::plugins::misc::powershell_encoded($ps);
    }

    my ($stdout) = centreon::plugins::misc::execute(
        output => $self->{output},
        options => $self->{option_results},
        command => $self->{option_results}->{command},
        command_path => $self->{option_results}->{command_path},
        command_options => $self->{option_results}->{command_options}
    );
    if (defined($self->{option_results}->{ps_exec_only})) {
        $self->{output}->output_add(
            severity => 'OK',
            short_msg => $stdout
        );
        $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
        $self->{output}->exit();
    }

    my $decoded;
    eval {
        $decoded = JSON::XS->new->decode($stdout);
    };
    if ($@) {
        $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@");
        $self->{output}->option_exit();
    }

    #[
    #   {
    #     "name": "test1", "state": 2, "integration_services_state": "Update required", "integration_services_version": "3.1", "note": null,
    #     "services": [
    #         { "service": "Time Synchronization", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "Key-Value Pair Exchange", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "Shutdown", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "VSS", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "Guest Service Interface", "enabled": false, "primary_operational_status": 2, "secondary_operational_status": null }
    #     ]
    #   },
    #   {
    #     "name": "test2", "state": 2, "integration_services_state": null, "integration_services_version": null, "note": null,
    #     "services": [
    #         { "service": "Time Synchronization", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "Key-Value Pair Exchange", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "Shutdown", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "VSS", "enabled": true, "primary_operational_status": 12, "secondary_operational_status": null },
    #         { "service": "Guest Service Interface", "enabled": false, "primary_operational_status": 2, "secondary_operational_status": null }
    #     ]
    #   }
    #]
    $self->{vm} = {};

    my $id = 1;
    foreach my $node (@$decoded) {
        if (defined($self->{option_results}->{filter_vm}) && $self->{option_results}->{filter_vm} ne '' &&
            $node->{name} !~ /$self->{option_results}->{filter_vm}/i) {
            $self->{output}->output_add(long_msg => "skipping  '" . $node->{name} . "': no matching filter.", debug => 1);
            next;
        }
        if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status} ne '' &&
            $node_vm_state->{ $node->{state} } !~ /$self->{option_results}->{filter_status}/i) {
            $self->{output}->output_add(long_msg => "skipping  '" . $node->{name} . "': no matching filter.", debug => 1);
            next;
        }
        if (defined($self->{option_results}->{filter_note}) && $self->{option_results}->{filter_note} ne '' &&
            defined($node->{note}) && $node->{note} !~ /$self->{option_results}->{filter_note}/i) {
            $self->{output}->output_add(long_msg => "skipping  '" . $node->{name} . "': no matching filter.", debug => 1);
            next;
        }

        $self->{vm}->{$id} = {
            vm => $node->{name},
            service => {}
        };
        $self->{vm}->{$id}->{global} = {
            $node->{name} => {
                vm => $node->{name},
                integration_service_state => defined($node->{integration_services_state}) ? $node->{integration_services_state} : '-',
                integration_service_version => defined($node->{integration_services_version}) ? $node->{integration_services_version} : '-',
                state => $node_vm_state->{ $node->{state} }
            }
        };

        my $id2 = 1;
        my $services = (ref($node->{services}) eq 'ARRAY') ? $node->{services} : [ $node->{services} ];

        foreach my $service (@$services) {
            $self->{vm}->{$id}->{service}->{$id2} = {
                vm => $node->{name},
                service => $service->{service},
                enabled => $service->{enabled} =~ /True|1/i ? 1 : 0,
                primary_status =>
                    defined($service->{primary_operational_status}) && defined($node_vm_integration_service_operational_status->{ $service->{primary_operational_status} }) ?
                        $node_vm_integration_service_operational_status->{ $service->{primary_operational_status} } : '-',
                secondary_status =>
                    defined($service->{secondary_operational_status}) && defined($node_vm_integration_service_operational_status->{ $service->{secondary_operational_status} }) ?
                        $node_vm_integration_service_operational_status->{ $service->{secondary_operational_status} } : '-'
            };
            $id2++;
        }

        $id++;
    }
}

1;

__END__

=head1 MODE

Check virtual machine integration services on hyper-v node.

=over 8

=item B<--timeout>

Set timeout time for command execution (Default: 50 sec)

=item B<--no-ps>

Don't encode powershell. To be used with --command and 'type' command.

=item B<--command>

Command to get information (Default: 'powershell.exe').
Can be changed if you have output in a file. To be used with --no-ps option!!!

=item B<--command-path>

Command path (Default: none).

=item B<--command-options>

Command options (Default: '-InputFormat none -NoLogo -EncodedCommand').

=item B<--ps-display>

Display powershell script.

=item B<--ps-exec-only>

Print powershell output.

=item B<--filter-vm>

Filter virtual machines (can be a regexp).

=item B<--filter-note>

Filter by VM notes (can be a regexp).

=item B<--filter-status>

Filter virtual machine status (can be a regexp) (Default: 'running').

=item B<--warning-global-status>

Set warning threshold for status (Default: '%{integration_service_state} =~ /Update required/i').
Can used special variables like: %{vm}, %{integration_service_state},
%{integration_service_version}, %{state}

=item B<--critical-global-status>

Set critical threshold for status (Default: '').
Can used special variables like: %{vm}, %{integration_service_state},
%{integration_service_version}, %{state}

=item B<--warning-service-status>

Set warning threshold for status (Default: '').
Can used special variables like: %{vm}, %{service}, %{primary_status}, %{secondary_status}, %{enabled}

=item B<--critical-service-status>

Set critical threshold for status (Default: '%{primary_status} !~ /Ok/i').
Can used special variables like: %{vm}, %{service}, %{primary_status}, %{secondary_status}, %{enabled}

=back

=cut


text:
package com.example.lru.memory.disk.cache;

import com.lru.memory.disk.cache.AbstractCacheService;
import com.lru.memory.disk.cache.CacheEntry;

/**
 *
 * @author sathayeg
 */
public class ExampleCacheEntryCache extends AbstractCacheService<CacheEntry<ExampleObjectToCache>> {

    public ExampleCacheEntryCache(String cacheName, int cacheSize, boolean diskPersist, String dataDirectory) throws Exception {
        super(cacheName, cacheSize, diskPersist, dataDirectory);
    }

    @Override
    public boolean isCacheItemValid(CacheEntry<ExampleObjectToCache> o) {
        //item only valid for 5 seconds, after which it will be reloaded
        return ((System.currentTimeMillis() - o.getTimestamp()) < 5000);
    }

    @Override
    public CacheEntry<ExampleObjectToCache> loadData(String key) throws Exception {
        CacheEntry<ExampleObjectToCache> ce = null;
        if(key.equals("nullObject")){
             ce = new CacheEntry<>(null, System.currentTimeMillis());
        }else{
            ExampleObjectToCache obj = new ExampleObjectToCache(key);
            obj.setData("data for key: " + key);
            obj.setLastModfied(System.currentTimeMillis());
            ce = new CacheEntry<>(obj, System.currentTimeMillis());
        }
        return ce;
    }

}


text:
from unittest import TestCase
from Rammbock.templates.containers import Protocol, MessageTemplate
from Rammbock.templates.primitives import UInt, PDU
from Rammbock.binary_tools import to_bin
from .tools import *

class TestStructs(TestCase):

    def test_access_struct(self):
        self._protocol = Protocol('TestProtocol')
        self._protocol.add(UInt(2, 'msgId', 5))
        self._protocol.add(UInt(2, 'length', None))
        self._protocol.add(PDU('length-4'))
        self.tmp = MessageTemplate('StructuredRequest', self._protocol, {})
        struct = get_pair()
        self.tmp.add(struct)
        msg = self.tmp.encode({}, {})
        self.assertEquals(msg.pair.first.int, 1)

    def test_create_struct(self):
        struct = get_pair()
        self.assertEquals(struct.name, 'pair')

    def test_add_fields_to_struct(self):
        struct = get_pair()
        encoded = struct.encode({}, {})
        self.assertEquals(encoded.first.int, 1)

    def test_add_fields_to_struct_and_override_values(self):
        struct = get_pair()
        encoded = struct.encode({'pair.first': 42}, {})
        self.assertEquals(encoded.first.int, 42)

    def test_yo_dawg_i_heard(self):
        str_str = get_recursive_struct()
        encoded = str_str.encode({}, {})
        self.assertEquals(encoded.pair.first.int, 1)

    def test_get_recursive_names(self):
        pair = get_pair()
        names = pair._get_params_sub_tree({'pair.foo': 0, 'pairnotyourname.ploo': 2, 'pair.goo.doo': 3})
        self.assertEquals(len(names), 2)
        self.assertEquals(names['foo'], 0)
        self.assertEquals(names['goo.doo'], 3)

    def test_set_recursive(self):
        str_str = get_recursive_struct()
        encoded = str_str.encode({'str_str.pair.first': 42}, {})
        self.assertEquals(encoded.pair.first.int, 42)

    def test_decode_several_structs(self):
        str_list = get_struct_list()
        decoded = str_list.decode(to_bin('0xcafebabe d00df00d'), {})
        self.assertEquals(decoded[0].first.hex, '0xcafe')
        self.assertEquals(decoded[1].second.hex, '0xf00d')

    def test_length_of_struct(self):
        pair = get_pair()
        encoded = pair.encode({}, {})
        self.assertEquals(len(encoded), 4)

    def test_decode_struct(self):
        pair = get_pair()
        decoded = pair.decode(to_bin('0xcafebabe'), {})
        self.assertEquals(decoded.first.hex, '0xcafe')
        self.assertEquals(decoded.second.hex, '0xbabe')

    def test_decode_aligned(self):
        struct = get_struct_with_length_and_alignment()
        decoded = struct.decode(to_bin('0x00010200'), {})
        self.assertEqual(decoded.first.int, 1)
        self.assertEqual(decoded.second.int, 2)
        self.assertEqual(len(decoded), 4)
        self.assertEqual(decoded._raw, to_bin('0x00010200'))

    def test_encode_aligned(self):
        struct = get_struct_with_length_and_alignment()
        encoded = struct.encode({}, {})
        self.assertEqual(encoded.first.int, 1)
        self.assertEqual(encoded.second.int, 2)
        self.assertEqual(len(encoded), 4)
        self.assertEqual(encoded._raw, to_bin('0x00010200'))

    def test_encode_perfectly_aligned(self):
        struct = get_struct_with_length_and_alignment()
        struct.add(UInt(5, 'third', 3))
        encoded = struct.encode({}, {})
        self.assertEqual(encoded.first.int, 1)
        self.assertEqual(encoded.second.int, 2)
        self.assertEqual(encoded.third.int, 3)
        self.assertEqual(len(encoded), 8)
        self.assertEqual(encoded._raw, to_bin('0x00010200 00000003'))