text:
package org.glowroot.agent.impl;

import java.lang.management.ThreadInfo;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.google.common.base.Strings;
import com.google.common.base.Ticker;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
import com.google.common.primitives.Ints;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.glowroot.agent.bytecode.api.BytecodeServiceHolder;
import org.glowroot.agent.bytecode.api.ThreadContextPlus;
import org.glowroot.agent.bytecode.api.ThreadContextThreadLocal;
import org.glowroot.agent.impl.NopTransactionService.NopTimer;
import org.glowroot.agent.model.AsyncQueryData;
import org.glowroot.agent.model.AsyncTimer;
import org.glowroot.agent.model.ErrorMessage;
import org.glowroot.agent.model.QueryCollector;
import org.glowroot.agent.model.QueryData;
import org.glowroot.agent.model.QueryDataMap;
import org.glowroot.agent.model.QueryEntryBase;
import org.glowroot.agent.model.ServiceCallCollector;
import org.glowroot.agent.model.SyncQueryData;
import org.glowroot.agent.model.ThreadStats;
import org.glowroot.agent.model.ThreadStatsComponent;
import org.glowroot.agent.model.TimerNameImpl;
import org.glowroot.agent.plugin.api.AsyncQueryEntry;
import org.glowroot.agent.plugin.api.AsyncTraceEntry;
import org.glowroot.agent.plugin.api.AuxThreadContext;
import org.glowroot.agent.plugin.api.MessageSupplier;
import org.glowroot.agent.plugin.api.QueryEntry;
import org.glowroot.agent.plugin.api.QueryMessageSupplier;
import org.glowroot.agent.plugin.api.ThreadContext;
import org.glowroot.agent.plugin.api.Timer;
import org.glowroot.agent.plugin.api.TimerName;
import org.glowroot.agent.plugin.api.TraceEntry;
import org.glowroot.agent.util.ThreadAllocatedBytes;
import org.glowroot.agent.util.Tickers;
import org.glowroot.common.config.AdvancedConfig;
import org.glowroot.common.util.NotAvailableAware;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.glowroot.agent.util.Checkers.castInitialized;

public class ThreadContextImpl implements ThreadContextPlus {

    private static final boolean CAPTURE_AUXILIARY_THREAD_LOCATION_STACK_TRACES =
            Boolean.getBoolean("glowroot.debug.captureAuxiliaryThreadLocationStackTraces");

    private static final String LIMIT_EXCEEDED_BUCKET = "LIMIT EXCEEDED BUCKET";

    private static final MessageSupplier DETACHED_MESSAGE_SUPPLIER = MessageSupplier
            .create("this auxiliary thread was still running when the transaction ended");

    private static final Logger logger = LoggerFactory.getLogger(ThreadContextImpl.class);

    private final Transaction transaction;
    // this is null for main thread, and non-null for auxiliary threads
    private final @Nullable TraceEntryImpl parentTraceEntry;
    // this is null for main thread, and non-null for auxiliary threads
    // it is used to help place aux thread context in the correct place inside parent
    private final @Nullable TraceEntryImpl parentThreadContextPriorEntry;

    private final TimerImpl rootTimer;
    // only accessed by the thread context's thread
    private @Nullable TimerImpl currentTimer;

    private int currentNestingGroupId;
    private int currentSuppressionKeyId;

    private final @Nullable ThreadStatsComponent threadStatsComponent;

    // root entry for this trace
    private final TraceEntryComponent traceEntryComponent;

    // only accessed by the thread context's thread
    private boolean transactionAsyncComplete;

    // linked lists of SyncQueryData instances for safe concurrent access
    private @MonotonicNonNull SyncQueryData headQueryData;
    private @MonotonicNonNull SyncQueryData headServiceCallData;
    // these maps are only accessed by the thread context's thread
    private @MonotonicNonNull QueryDataMap queriesForFirstType;
    private @MonotonicNonNull Map<String, QueryDataMap> allQueryTypesMap;
    private @MonotonicNonNull QueryDataMap serviceCallsForFirstType;
    private @MonotonicNonNull Map<String, QueryDataMap> allServiceCallTypesMap;

    private int queryAggregateCounter;
    private int serviceCallAggregateCounter;

    private final int maxQueryAggregates;
    private final int maxServiceCallAggregates;

    private final long threadId;

    private final boolean limitExceededAuxThreadContext;

    private final Ticker ticker;

    private final ThreadContextThreadLocal.Holder threadContextHolder;

    private @Nullable ServletRequestInfo servletRequestInfo;

    private volatile boolean mayHaveChildAuxThreadContext;

    private volatile boolean detached;

    // only ever non-null for main thread context
    private final @Nullable ThreadContextImpl outerTransactionThreadContext;

    // this is needed in for pointcuts that startTransaction() on an outer transaction thread
    // context, and then proceed to immediately call setTransaction...() on that same outer
    // transaction thread context
    private @Nullable ThreadContextImpl innerTransactionThreadContext;

    ThreadContextImpl(Transaction transaction, @Nullable TraceEntryImpl parentTraceEntry,
            @Nullable TraceEntryImpl parentThreadContextPriorEntry, MessageSupplier messageSupplier,
            TimerName rootTimerName, long startTick, boolean captureThreadStats,
            int maxQueryAggregates, int maxServiceCallAggregates,
            @Nullable ThreadAllocatedBytes threadAllocatedBytes,
            boolean limitExceededAuxThreadContext, Ticker ticker,
            ThreadContextThreadLocal.Holder threadContextHolder,
            @Nullable ServletRequestInfo servletRequestInfo, int rootNestingGroupId,
            int rootSuppressionKeyId) {
        this.transaction = transaction;
        this.parentTraceEntry = parentTraceEntry;
        rootTimer = TimerImpl.createRootTimer(castInitialized(this), (TimerNameImpl) rootTimerName);
        rootTimer.start(startTick);
        traceEntryComponent = new TraceEntryComponent(castInitialized(this), messageSupplier,
                rootTimer, startTick);
        this.parentThreadContextPriorEntry = parentThreadContextPriorEntry;
        threadId = Thread.currentThread().getId();
        threadStatsComponent =
                captureThreadStats ? new ThreadStatsComponent(threadAllocatedBytes) : null;
        this.maxQueryAggregates = maxQueryAggregates;
        this.maxServiceCallAggregates = maxServiceCallAggregates;
        this.limitExceededAuxThreadContext = limitExceededAuxThreadContext;
        this.ticker = ticker;
        this.threadContextHolder = threadContextHolder;
        this.servletRequestInfo = servletRequestInfo;
        this.outerTransactionThreadContext = (ThreadContextImpl) threadContextHolder.get();
        currentNestingGroupId = rootNestingGroupId;
        currentSuppressionKeyId = rootSuppressionKeyId;
    }

    public Transaction getTransaction() {
        return transaction;
    }

    @Nullable
    TraceEntryImpl getParentThreadContextPriorEntry() {
        return parentThreadContextPriorEntry;
    }

    TraceEntryImpl getTailEntry() {
        return traceEntryComponent.getTailEntry();
    }

    TraceEntryImpl getRootEntry() {
        return traceEntryComponent.getRootEntry();
    }

    TimerImpl getRootTimer() {
        return rootTimer;
    }

    ThreadStats getThreadStats() {
        if (threadStatsComponent == null) {
            return ThreadStats.NA;
        }
        return threadStatsComponent.getThreadStats();
    }

    long getCpuNanos() {
        if (threadStatsComponent == null) {
            return NotAvailableAware.NA;
        }
        return threadStatsComponent.getCpuNanos();
    }

    public long getThreadId() {
        return threadId;
    }

    boolean isCompleted() {
        return traceEntryComponent.isCompleted();
    }

    public boolean isActive() {
        // checking threadContextHolder.get() to make sure this isn't an outer transaction on hold
        // while inner transaction is executing
        return !traceEntryComponent.isCompleted() && threadContextHolder.get() == this;
    }

    public @Nullable TimerImpl getCurrentTimer() {
        return currentTimer;
    }

    void setCurrentTimer(@Nullable TimerImpl currentTimer) {
        this.currentTimer = currentTimer;
    }

    @Override
    public int getCurrentNestingGroupId() {
        return currentNestingGroupId;
    }

    @Override
    public void setCurrentNestingGroupId(int nestingGroupId) {
        this.currentNestingGroupId = nestingGroupId;
    }

    @Override
    public int getCurrentSuppressionKeyId() {
        return currentSuppressionKeyId;
    }

    @Override
    public void setCurrentSuppressionKeyId(int suppressionKeyId) {
        this.currentSuppressionKeyId = suppressionKeyId;
    }

    // FIXME why is this safe when called from another thread?
    boolean isMergeable() {
        return !mayHaveChildAuxThreadContext && traceEntryComponent.isEmpty();
    }

    void mergeQueriesInto(QueryCollector collector) {
        SyncQueryData curr = headQueryData;
        while (curr != null) {
            collector.mergeQuery(curr.getQueryType(), curr.getQueryText(),
                    curr.getTotalDurationNanos(ticker), curr.getExecutionCount(),
                    curr.hasTotalRows(), curr.getTotalRows(), curr.isActive());
            curr = curr.getNextQueryData();
        }
    }

    void mergeServiceCallsInto(ServiceCallCollector collector) {
        SyncQueryData curr = headServiceCallData;
        while (curr != null) {
            collector.mergeServiceCall(curr.getQueryType(), curr.getQueryText(),
                    curr.getTotalDurationNanos(ticker), curr.getExecutionCount());
            curr = curr.getNextQueryData();
        }
    }

    boolean getCaptureThreadStats() {
        return threadStatsComponent != null;
    }

    private boolean isCompleted(long captureTick) {
        if (!traceEntryComponent.isCompleted()) {
            return false;
        }
        return traceEntryComponent.getEndTick() >= captureTick;
    }

    // only called by transaction thread
    private SyncQueryData getOrCreateQueryData(String queryType, String queryText,
            boolean bypassLimit) {
        if (headQueryData == null) {
            queriesForFirstType = new QueryDataMap(queryType);
            return createQueryData(queriesForFirstType, queryType, queryText, bypassLimit);
        }
        QueryDataMap queriesForType = checkNotNull(queriesForFirstType);
        if (!queriesForType.getType().equals(queryType)) {
            queriesForType = getOrCreateQueriesForType(queryType);
        }
        SyncQueryData queryData = queriesForType.get(queryText);
        if (queryData == null) {
            queryData = createQueryData(queriesForType, queryType, queryText, bypassLimit);
        }
        return queryData;
    }

    private SyncQueryData createQueryData(QueryDataMap queriesForType, String queryType,
            String queryText, boolean bypassLimit) {
        if (allowAnotherQueryAggregate(bypassLimit)) {
            return createQueryData(queriesForType, queryType, queryText);
        } else {
            SyncQueryData limitExceededBucket = queriesForType.get(LIMIT_EXCEEDED_BUCKET);
            if (limitExceededBucket == null) {
                limitExceededBucket = createQueryData(queriesForType, queryType,
                        LIMIT_EXCEEDED_BUCKET);
            }
            return new SyncQueryData(queryType, queryText, null, limitExceededBucket);
        }
    }

    private SyncQueryData createQueryData(QueryDataMap queriesForType, String queryType,
            String queryText) {
        SyncQueryData queryData = new SyncQueryData(queryType, queryText, headQueryData, null);
        queriesForType.put(queryText, queryData);
        headQueryData = queryData;
        return queryData;
    }

    // only called by transaction thread
    private SyncQueryData getOrCreateServiceCallData(String serviceCallType, String serviceCallText,
            boolean bypassLimit) {
        if (headServiceCallData == null) {
            serviceCallsForFirstType = new QueryDataMap(serviceCallType);
            return createServiceCallData(serviceCallsForFirstType, serviceCallType, serviceCallText,
                    bypassLimit);
        }
        QueryDataMap serviceCallsForType = checkNotNull(serviceCallsForFirstType);
        if (!serviceCallsForType.getType().equals(serviceCallType)) {
            serviceCallsForType = getOrCreateServiceCallsForType(serviceCallType);
        }
        SyncQueryData serviceCallData = serviceCallsForType.get(serviceCallText);
        if (serviceCallData == null) {
            serviceCallData = createServiceCallData(serviceCallsForType, serviceCallType,
                    serviceCallText, bypassLimit);
        }
        return serviceCallData;
    }

    private SyncQueryData createServiceCallData(QueryDataMap serviceCallsForType,
            String serviceCallType, String serviceCallText, boolean bypassLimit) {
        if (allowAnotherServiceCallAggregate(bypassLimit)) {
            return createServiceCallData(serviceCallsForType, serviceCallType,
                    serviceCallText);
        } else {
            SyncQueryData limitExceededBucket =
                    serviceCallsForType.get(LIMIT_EXCEEDED_BUCKET);
            if (limitExceededBucket == null) {
                limitExceededBucket =
                        createServiceCallData(serviceCallsForType, serviceCallType,
                                LIMIT_EXCEEDED_BUCKET);
            }
            return new SyncQueryData(serviceCallType, serviceCallText, null, limitExceededBucket);
        }
    }

    private SyncQueryData createServiceCallData(QueryDataMap serviceCallsForType,
            String serviceCallType, String serviceCallText) {
        SyncQueryData serviceCallData =
                new SyncQueryData(serviceCallType, serviceCallText, headServiceCallData, null);
        serviceCallsForType.put(serviceCallText, serviceCallData);
        headServiceCallData = serviceCallData;
        return serviceCallData;
    }

    // this method has side effect of incrementing counter
    private boolean allowAnotherQueryAggregate(boolean bypassLimit) {
        return queryAggregateCounter++ < maxQueryAggregates
                * AdvancedConfig.OVERALL_AGGREGATE_QUERIES_HARD_LIMIT_MULTIPLIER
                || bypassLimit;
    }

    // this method has side effect of incrementing counter
    private boolean allowAnotherServiceCallAggregate(boolean bypassLimit) {
        return serviceCallAggregateCounter++ < maxServiceCallAggregates
                * AdvancedConfig.OVERALL_AGGREGATE_SERVICE_CALLS_HARD_LIMIT_MULTIPLIER
                || bypassLimit;
    }

    TraceEntryImpl addErrorEntry(long startTick, long endTick, @Nullable Object messageSupplier,
            @Nullable QueryData queryData, ErrorMessage errorMessage) {
        TraceEntryImpl entry = traceEntryComponent.addErrorEntry(startTick, endTick,
                messageSupplier, queryData, errorMessage);
        // memory barrier write ensures partial trace capture will see data collected up to now
        // memory barrier read ensures timely visibility of detach()
        transaction.memoryBarrierReadWrite();
        return entry;
    }

    private TraceEntryImpl startAsyncTraceEntry(long startTick, MessageSupplier messageSupplier,
            TimerImpl syncTimer, AsyncTimer asyncTimer) {
        TraceEntryImpl entry = traceEntryComponent.pushEntry(startTick, messageSupplier, syncTimer,
                asyncTimer, null, 0);
        // memory barrier write ensures partial trace capture will see data collected up to now
        // memory barrier read ensures timely visibility of detach()
        transaction.memoryBarrierReadWrite();
        return entry;
    }

    private TraceEntryImpl startAsyncQueryEntry(long startTick,
            QueryMessageSupplier queryMessageSupplier, TimerImpl syncTimer,
            AsyncTimer asyncTimer, @Nullable QueryData queryData, long queryExecutionCount) {
        TraceEntryImpl entry =
                traceEntryComponent.pushEntry(startTick, queryMessageSupplier, syncTimer,
                        asyncTimer, queryData, queryExecutionCount);
        // memory barrier write ensures partial trace capture will see data collected up to now
        // memory barrier read ensures timely visibility of detach()
        transaction.memoryBarrierReadWrite();
        return entry;
    }

    private TraceEntryImpl startAsyncServiceCallEntry(long startTick,
            MessageSupplier messageSupplier, TimerImpl syncTimer, AsyncTimer asyncTimer,
            @Nullable QueryData queryData) {
        TraceEntryImpl entry = traceEntryComponent.pushEntry(startTick, messageSupplier,
                syncTimer, asyncTimer, queryData, 1);
        // memory barrier write ensures partial trace capture will see data collected up to now
        // memory barrier read ensures timely visibility of detach()
        transaction.memoryBarrierReadWrite();
        return entry;
    }

    void captureStackTrace(ThreadInfo threadInfo) {
        transaction.captureStackTrace(isAuxiliary(), threadInfo);
        // memory barrier read ensures timely visibility of detach()
        transaction.memoryBarrierRead();
    }

    @Override
    public AuxThreadContext createAuxThreadContext() {
        ImmutableList<StackTraceElement> locationStackTrace = null;
        if (CAPTURE_AUXILIARY_THREAD_LOCATION_STACK_TRACES) {
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            // strip up through this method, plus 1 additional method (the plugin advice method)
            int index = getNormalizedStartIndex(stackTrace, "createAuxThreadContext", 1);
            locationStackTrace = ImmutableList.copyOf(stackTrace).subList(index, stackTrace.length);
        }
        if (limitExceededAuxThreadContext) {
            // no auxiliary thread context hierarchy after limit exceeded in order to limit the
            // retention of auxiliary thread contexts
            return new AuxThreadContextImpl(transaction, null, null, servletRequestInfo,
                    locationStackTrace, transaction.getTransactionRegistry(),
                    transaction.getTransactionService());
        } else {
            mayHaveChildAuxThreadContext = true;
            return new AuxThreadContextImpl(transaction, traceEntryComponent.getActiveEntry(),
                    traceEntryComponent.getTailEntry(), servletRequestInfo, locationStackTrace,
                    transaction.getTransactionRegistry(), transaction.getTransactionService());
        }
    }

    // typically pop() methods don't require the objects to pop, but for safety, the entry to pop is
    // passed in just to make sure it is the one on top (and if not, then pop until is is found,
    // preventing any nasty bugs from a missed pop, e.g. a trace never being marked as complete)
    void popEntry(TraceEntryImpl entry, long endTick) {
        traceEntryComponent.popEntry(entry, endTick);
        // memory barrier write ensures partial trace capture will see data collected up to now
        // memory barrier read ensures timely visibility of detach()
        transaction.memoryBarrierReadWrite();
        if (traceEntryComponent.isCompleted()) {
            if (threadStatsComponent != null) {
                threadStatsComponent.onComplete();
            }
            if (limitExceededAuxThreadContext) {
                // this is a limit exceeded auxiliary thread context
                transaction.mergeLimitExceededAuxThreadContext(this);
            }
            if (!isAuxiliary() || transactionAsyncComplete) {
                transaction.end(endTick, transactionAsyncComplete, false);
            }
            threadContextHolder.set(outerTransactionThreadContext);
            if (outerTransactionThreadContext != null) {
                outerTransactionThreadContext.innerTransactionThreadContext = null;
            }
        }
    }

    // typically pop() methods don't require the objects to pop, but for safety, the entry to pop is
    // passed in just to make sure it is the one on top (and if not, then pop until is is found,
    // preventing any nasty bugs from a missed pop, e.g. a trace never being marked as complete)
    void popNonRootEntry(TraceEntryImpl entry) {
        traceEntryComponent.popNonRootEntry(entry);
        // memory barrier write ensures partial trace capture will see data collected up to now
        // memory barrier read ensures timely visibility of detach()
        transaction.memoryBarrierReadWrite();
    }

    // detach is called from another thread
    void detach() {
        // this synchronization protects against clobbering valid thread context in race condition
        // where thread context ends naturally and thread re-starts a new thread context quickly
        // see counterpart to this synchronized block in startAuxThreadContext()
        synchronized (threadContextHolder) {
            if (threadContextHolder.get() == this) {
                threadContextHolder.set(null);
            }
        }
        // memory barrier write is needed to ensure the running thread sees that the thread
        // context holder has been cleared (at least after the thread completes its next trace entry
        // or profile sample, which both perform memory barrier reads)
        transaction.memoryBarrierWrite();
        detached = true;
    }

    private QueryDataMap getOrCreateQueriesForType(String queryType) {
        if (allQueryTypesMap == null) {
            allQueryTypesMap = new HashMap<String, QueryDataMap>(2);
            QueryDataMap queriesForType = new QueryDataMap(queryType);
            allQueryTypesMap.put(queryType, queriesForType);
            return queriesForType;
        }
        QueryDataMap queriesForType = allQueryTypesMap.get(queryType);
        if (queriesForType == null) {
            queriesForType = new QueryDataMap(queryType);
            allQueryTypesMap.put(queryType, queriesForType);
        }
        return queriesForType;
    }

    private QueryDataMap getOrCreateServiceCallsForType(String type) {
        if (allServiceCallTypesMap == null) {
            allServiceCallTypesMap = new HashMap<String, QueryDataMap>(2);
            QueryDataMap serviceCallsForType = new QueryDataMap(type);
            allServiceCallTypesMap.put(type, serviceCallsForType);
            return serviceCallsForType;
        }
        QueryDataMap serviceCallsForType = allServiceCallTypesMap.get(type);
        if (serviceCallsForType == null) {
            serviceCallsForType = new QueryDataMap(type);
            allServiceCallTypesMap.put(type, serviceCallsForType);
        }
        return serviceCallsForType;
    }

    @Override
    public boolean isInTransaction() {
        return true;
    }

    @Override
    public TraceEntry startTransaction(String transactionType, String transactionName,
            MessageSupplier messageSupplier, TimerName timerName) {
        return startTransaction(transactionType, transactionName, messageSupplier, timerName,
                AlreadyInTransactionBehavior.CAPTURE_TRACE_ENTRY);
    }

    @Override
    public TraceEntry startTransaction(String transactionType, String transactionName,
            MessageSupplier messageSupplier, TimerName timerName,
            AlreadyInTransactionBehavior alreadyInTransactionBehavior) {
        if (transactionType == null) {
            logger.error("startTransaction(): argument 'transactionType' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        if (transactionName == null) {
            logger.error("startTransaction(): argument 'transactionName' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        if (messageSupplier == null) {
            logger.error("startTransaction(): argument 'messageSupplier' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        if (timerName == null) {
            logger.error("startTransaction(): argument 'timerName' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        // ensure visibility of recent configuration updates
        transaction.getConfigService().readMemoryBarrier();
        if (transaction.isOuter()
                || alreadyInTransactionBehavior == AlreadyInTransactionBehavior.CAPTURE_NEW_TRANSACTION) {
            TraceEntryImpl traceEntry = transaction.startInnerTransaction(transactionType,
                    transactionName, messageSupplier, timerName, threadContextHolder,
                    currentNestingGroupId, currentSuppressionKeyId);
            innerTransactionThreadContext =
                    (ThreadContextImpl) checkNotNull(threadContextHolder.get());
            return traceEntry;
        }
        long startTick = ticker.read();
        TimerImpl timer = startTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            return traceEntryComponent.pushEntry(startTick, messageSupplier, timer, null, null, 0);
        } else {
            return new DummyTraceEntryOrQuery(timer, null, startTick, messageSupplier, null, 0);
        }
    }

    @Override
    public TraceEntry startTraceEntry(MessageSupplier messageSupplier, TimerName timerName) {
        if (messageSupplier == null) {
            logger.error("startTraceEntry(): argument 'messageSupplier' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        if (timerName == null) {
            logger.error("startTraceEntry(): argument 'timerName' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        long startTick = ticker.read();
        TimerImpl timer = startTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            return traceEntryComponent.pushEntry(startTick, messageSupplier, timer, null, null, 0);
        } else {
            return new DummyTraceEntryOrQuery(timer, null, startTick, messageSupplier, null, 0);
        }
    }

    @Override
    public AsyncTraceEntry startAsyncTraceEntry(MessageSupplier messageSupplier,
            TimerName timerName) {
        if (messageSupplier == null) {
            logger.error("startAsyncTraceEntry(): argument 'messageSupplier' must be non-null");
            return NopTransactionService.ASYNC_TRACE_ENTRY;
        }
        if (timerName == null) {
            logger.error("startAsyncTraceEntry(): argument 'timerName' must be non-null");
            return NopTransactionService.ASYNC_TRACE_ENTRY;
        }
        long startTick = ticker.read();
        TimerImpl syncTimer = startTimer(timerName, startTick);
        AsyncTimer asyncTimer = transaction.startAsyncTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            return startAsyncTraceEntry(startTick, messageSupplier, syncTimer, asyncTimer);
        } else {
            return new DummyTraceEntryOrQuery(syncTimer, asyncTimer, startTick, messageSupplier,
                    null, 0);
        }
    }

    @Override
    public QueryEntry startQueryEntry(String queryType, String queryText,
            QueryMessageSupplier queryMessageSupplier, TimerName timerName) {
        if (queryType == null) {
            logger.error("startQueryEntry(): argument 'queryType' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        if (queryText == null) {
            logger.error("startQueryEntry(): argument 'queryText' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        if (queryMessageSupplier == null) {
            logger.error("startQueryEntry(): argument 'queryMessageSupplier' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        if (timerName == null) {
            logger.error("startQueryEntry(): argument 'timerName' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        long startTick = ticker.read();
        TimerImpl timer = startTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            SyncQueryData queryData = getOrCreateQueryData(queryType, queryText, true);
            return traceEntryComponent.pushEntry(startTick, queryMessageSupplier, timer, null,
                    queryData, 1);
        } else {
            SyncQueryData queryData = getOrCreateQueryData(queryType, queryText, false);
            return new DummyTraceEntryOrQuery(timer, null, startTick, queryMessageSupplier,
                    queryData, 1);
        }
    }

    @Override
    public QueryEntry startQueryEntry(String queryType, String queryText, long queryExecutionCount,
            QueryMessageSupplier queryMessageSupplier, TimerName timerName) {
        if (queryType == null) {
            logger.error("startQueryEntry(): argument 'queryType' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        if (queryText == null) {
            logger.error("startQueryEntry(): argument 'queryText' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        if (queryExecutionCount <= 0) {
            logger.error("startQueryEntry(): argument 'queryExecutionCount' must be positive");
            return NopTransactionService.QUERY_ENTRY;
        }
        if (queryMessageSupplier == null) {
            logger.error("startQueryEntry(): argument 'queryMessageSupplier' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        if (timerName == null) {
            logger.error("startQueryEntry(): argument 'timerName' must be non-null");
            return NopTransactionService.QUERY_ENTRY;
        }
        long startTick = ticker.read();
        TimerImpl timer = startTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            SyncQueryData queryData = getOrCreateQueryData(queryType, queryText, true);
            return traceEntryComponent.pushEntry(startTick, queryMessageSupplier, timer, null,
                    queryData, queryExecutionCount);
        } else {
            SyncQueryData queryData = getOrCreateQueryData(queryType, queryText, false);
            return new DummyTraceEntryOrQuery(timer, null, startTick, queryMessageSupplier,
                    queryData, queryExecutionCount);
        }
    }

    @Override
    public AsyncQueryEntry startAsyncQueryEntry(String queryType, String queryText,
            QueryMessageSupplier queryMessageSupplier, TimerName timerName) {
        if (queryType == null) {
            logger.error("startAsyncQueryEntry(): argument 'queryType' must be non-null");
            return NopTransactionService.ASYNC_QUERY_ENTRY;
        }
        if (queryText == null) {
            logger.error("startAsyncQueryEntry(): argument 'queryText' must be non-null");
            return NopTransactionService.ASYNC_QUERY_ENTRY;
        }
        if (queryMessageSupplier == null) {
            logger.error(
                    "startAsyncQueryEntry(): argument 'queryMessageSupplier' must be non-null");
            return NopTransactionService.ASYNC_QUERY_ENTRY;
        }
        if (timerName == null) {
            logger.error("startAsyncQueryEntry(): argument 'timerName' must be non-null");
            return NopTransactionService.ASYNC_QUERY_ENTRY;
        }
        long startTick = ticker.read();
        TimerImpl syncTimer = startTimer(timerName, startTick);
        AsyncTimer asyncTimer = transaction.startAsyncTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            AsyncQueryData queryData =
                    transaction.getOrCreateAsyncQueryData(queryType, queryText, true);
            return startAsyncQueryEntry(startTick, queryMessageSupplier, syncTimer, asyncTimer,
                    queryData, 1);
        } else {
            AsyncQueryData queryData =
                    transaction.getOrCreateAsyncQueryData(queryType, queryText, false);
            return new DummyTraceEntryOrQuery(syncTimer, asyncTimer, startTick,
                    queryMessageSupplier, queryData, 1);
        }
    }

    @Override
    public TraceEntry startServiceCallEntry(String serviceCallType, String serviceCallText,
            MessageSupplier messageSupplier, TimerName timerName) {
        if (serviceCallType == null) {
            logger.error("startServiceCallEntry(): argument 'serviceCallType' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        if (serviceCallText == null) {
            logger.error("startServiceCallEntry(): argument 'serviceCallText' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        if (messageSupplier == null) {
            logger.error("startServiceCallEntry(): argument 'messageSupplier' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        if (timerName == null) {
            logger.error("startServiceCallEntry(): argument 'timerName' must be non-null");
            return NopTransactionService.TRACE_ENTRY;
        }
        long startTick = ticker.read();
        TimerImpl timer = startTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            SyncQueryData queryData =
                    getOrCreateServiceCallData(serviceCallType, serviceCallText, true);
            return traceEntryComponent.pushEntry(startTick, messageSupplier, timer, null, queryData,
                    1);
        } else {
            SyncQueryData queryData =
                    getOrCreateServiceCallData(serviceCallType, serviceCallText, false);
            return new DummyTraceEntryOrQuery(timer, null, startTick, messageSupplier, queryData,
                    1);
        }
    }

    @Override
    public AsyncTraceEntry startAsyncServiceCallEntry(String serviceCallType,
            String serviceCallText, MessageSupplier messageSupplier, TimerName timerName) {
        if (serviceCallType == null) {
            logger.error(
                    "startAsyncServiceCallEntry(): argument 'serviceCallType' must be non-null");
            return NopTransactionService.ASYNC_TRACE_ENTRY;
        }
        if (serviceCallText == null) {
            logger.error(
                    "startAsyncServiceCallEntry(): argument 'serviceCallText' must be non-null");
            return NopTransactionService.ASYNC_TRACE_ENTRY;
        }
        if (messageSupplier == null) {
            logger.error(
                    "startAsyncServiceCallEntry(): argument 'messageSupplier' must be non-null");
            return NopTransactionService.ASYNC_TRACE_ENTRY;
        }
        if (timerName == null) {
            logger.error("startAsyncServiceCallEntry(): argument 'timerName' must be non-null");
            return NopTransactionService.ASYNC_TRACE_ENTRY;
        }
        long startTick = ticker.read();
        TimerImpl syncTimer = startTimer(timerName, startTick);
        AsyncTimer asyncTimer = transaction.startAsyncTimer(timerName, startTick);
        if (transaction.allowAnotherEntry()) {
            AsyncQueryData queryData = transaction.getOrCreateAsyncServiceCallData(serviceCallType,
                    serviceCallText, true);
            return startAsyncServiceCallEntry(startTick, messageSupplier, syncTimer, asyncTimer,
                    queryData);
        } else {
            AsyncQueryData queryData = transaction.getOrCreateAsyncServiceCallData(serviceCallType,
                    serviceCallText, false);
            return new DummyTraceEntryOrQuery(syncTimer, asyncTimer, startTick, messageSupplier,
                    queryData, 1);
        }
    }

    @Override
    public Timer startTimer(TimerName timerName) {
        if (timerName == null) {
            logger.error("startTimer(): argument 'timerName' must be non-null");
            return NopTimer.INSTANCE;
        }
        if (currentTimer == null) {
            logger.warn("startTimer(): called on completed thread context");
            return NopTimer.INSTANCE;
        }
        return currentTimer.startNestedTimer(timerName);
    }

    @Override
    public void setTransactionAsync() {
        if (innerTransactionThreadContext == null) {
            if (logger.isDebugEnabled() && AuxThreadContextImpl.inAuxDebugLogging.get() == null) {
                AuxThreadContextImpl.inAuxDebugLogging.set(Boolean.TRUE);
                try {
                    logger.debug("set async transaction, thread context: {}, parent thread context:"
                            + " {}, thread name: {}", hashCode(), getParentThreadContextDisplay(),
                            Thread.currentThread().getName(), new Exception());
                } finally {
                    AuxThreadContextImpl.inAuxDebugLogging.remove();
                }
            }
            transaction.setAsync();
        } else {
            innerTransactionThreadContext.setTransactionAsync();
        }
    }

    @Override
    public void setTransactionAsyncComplete() {
        if (innerTransactionThreadContext == null) {
            if (logger.isDebugEnabled() && AuxThreadContextImpl.inAuxDebugLogging.get() == null) {
                AuxThreadContextImpl.inAuxDebugLogging.set(Boolean.TRUE);
                try {
                    logger.debug("set async transaction complete, thread context: {},"
                            + " parent thread context: {}, thread name: {}", hashCode(),
                            getParentThreadContextDisplay(), Thread.currentThread().getName(),
                            new Exception());
                } finally {
                    AuxThreadContextImpl.inAuxDebugLogging.remove();
                }
            }
            transactionAsyncComplete = true;
            if (isCompleted()) {
                transaction.end(ticker.read(), true, true);
            } else {
                transaction.setWaitingToEndAsync();
            }
        } else {
            innerTransactionThreadContext.setTransactionAsyncComplete();
        }
    }

    @Override
    public void setTransactionOuter() {
        if (innerTransactionThreadContext == null) {
            transaction.setOuter();
        } else {
            innerTransactionThreadContext.setTransactionOuter();
        }
    }

    @Override
    public void setTransactionType(@Nullable String transactionType, int priority) {
        if (Strings.isNullOrEmpty(transactionType)) {
            return;
        }
        if (innerTransactionThreadContext == null) {
            transaction.setTransactionType(transactionType, priority);
        } else {
            innerTransactionThreadContext.setTransactionType(transactionType, priority);
        }
    }

    @Override
    public void setTransactionName(@Nullable String transactionName, int priority) {
        if (Strings.isNullOrEmpty(transactionName)) {
            return;
        }
        if (innerTransactionThreadContext == null) {
            transaction.setTransactionName(transactionName, priority);
        } else {
            innerTransactionThreadContext.setTransactionName(transactionName, priority);
        }
    }

    @Override
    public void setTransactionUser(@Nullable String user, int priority) {
        if (Strings.isNullOrEmpty(user)) {
            return;
        }
        if (innerTransactionThreadContext == null) {
            transaction.setUser(user, priority);
        } else {
            innerTransactionThreadContext.setTransactionUser(user, priority);
        }
    }

    @Override
    public void addTransactionAttribute(String name, @Nullable String value) {
        if (name == null) {
            logger.error("addTransactionAttribute(): argument 'name' must be non-null");
            return;
        }
        if (innerTransactionThreadContext == null) {
            transaction.addAttribute(name, value);
        } else {
            innerTransactionThreadContext.addTransactionAttribute(name, value);
        }
    }

    @Override
    public void setTransactionSlowThreshold(long threshold, TimeUnit unit, int priority) {
        if (threshold < 0) {
            logger.error(
                    "setTransactionSlowThreshold(): argument 'threshold' must be non-negative");
            return;
        }
        if (unit == null) {
            logger.error("setTransactionSlowThreshold(): argument 'unit' must be non-null");
            return;
        }
        if (innerTransactionThreadContext == null) {
            int thresholdMillis = Ints.saturatedCast(unit.toMillis(threshold));
            transaction.setSlowThresholdMillis(thresholdMillis, priority);
        } else {
            innerTransactionThreadContext.setTransactionSlowThreshold(threshold, unit, priority);
        }
    }

    @Override
    public void setTransactionError(Throwable t) {
        if (innerTransactionThreadContext == null) {
            transaction.setError(null, t);
        } else {
            innerTransactionThreadContext.setTransactionError(t);
        }
    }

    @Override
    public void setTransactionError(@Nullable String message) {
        if (Strings.isNullOrEmpty(message)) {
            return;
        }
        if (innerTransactionThreadContext == null) {
            transaction.setError(message, null);
        } else {
            innerTransactionThreadContext.setTransactionError(message);
        }
    }

    @Override
    public void setTransactionError(@Nullable String message, @Nullable Throwable t) {
        if (innerTransactionThreadContext == null) {
            transaction.setError(message, t);
        } else {
            innerTransactionThreadContext.setTransactionError(message, t);
        }
    }

    @Override
    public void addErrorEntry(Throwable t) {
        addErrorEntryInternal(null, t);
    }

    @Override
    public void addErrorEntry(@Nullable String message) {
        addErrorEntryInternal(message, null);
    }

    @Override
    public void addErrorEntry(@Nullable String message, Throwable t) {
        addErrorEntryInternal(message, t);
    }

    @Override
    public void trackResourceAcquired(Object resource, boolean withLocationStackTrace) {
        transaction.trackResourceAcquired(resource, withLocationStackTrace);
    }

    @Override
    public void trackResourceReleased(Object resource) {
        transaction.trackResourceReleased(resource);
    }

    @Override
    public @Nullable ServletRequestInfo getServletRequestInfo() {
        return servletRequestInfo;
    }

    @Override
    public void setServletRequestInfo(@Nullable ServletRequestInfo servletRequestInfo) {
        this.servletRequestInfo = servletRequestInfo;
    }

    boolean hasTraceEntries() {
        return !traceEntryComponent.isEmpty();
    }

    void populateParentChildMap(ListMultimap<TraceEntryImpl, TraceEntryImpl> parentChildMap,
            long captureTick,
            ListMultimap<TraceEntryImpl, ThreadContextImpl> priorEntryAuxThreadContextMap) {
        if (captureTick < traceEntryComponent.getStartTick()) {
            return;
        }
        boolean completed = isCompleted(captureTick);
        TraceEntryImpl entry = getRootEntry();
        boolean entryIsRoot = true;
        // filter out entries that started after the capture tick
        // checking completed is short circuit optimization for the common case
        while (entry != null
                && (completed || Tickers.lessThanOrEqual(entry.getStartTick(), captureTick))) {
            TraceEntryImpl parentTraceEntry = entry.getParentTraceEntry();
            if (parentTraceEntry == null && !entryIsRoot) {
                logger.error("found non-root trace entry with null parent trace entry"
                        + "\ntrace entry: {}\ntransaction: {} - {}", entry,
                        transaction.getTransactionType(), transaction.getTransactionName());
                entry = entry.getNextTraceEntry();
                continue;
            }
            if (!entryIsRoot) {
                parentChildMap.put(parentTraceEntry, entry);
            }
            for (ThreadContextImpl auxThreadContext : priorEntryAuxThreadContextMap.get(entry)) {
                TraceEntryImpl auxThreadRootEntry = auxThreadContext.getRootEntry();
                if (completed || Tickers.lessThanOrEqual(auxThreadRootEntry.getStartTick(),
                        captureTick)) {
                    // checkNotNull is safe b/c aux thread contexts have non-null parent trace entry
                    parentChildMap.put(checkNotNull(auxThreadContext.parentTraceEntry),
                            auxThreadRootEntry);
                }
            }
            entry = entry.getNextTraceEntry();
            entryIsRoot = false;
        }
        if (detached && !traceEntryComponent.isEmpty()) {
            TraceEntryImpl rootEntry = getRootEntry();
            parentChildMap.put(rootEntry,
                    new TraceEntryImpl(this, rootEntry, DETACHED_MESSAGE_SUPPLIER,
                            null, 0, transaction.getEndTick(), null, null));
        }
    }

    private boolean isAuxiliary() {
        return parentTraceEntry != null;
    }

    private void addErrorEntryInternal(@Nullable String message, @Nullable Throwable t) {
        // use higher entry limit when adding errors, but still need some kind of cap
        if (transaction.allowAnotherErrorEntry()) {
            long currTick = ticker.read();
            ErrorMessage errorMessage =
                    ErrorMessage.create(message, t, transaction.getThrowableFrameLimitCounter());
            addErrorEntry(currTick, currTick, null, null, errorMessage);
        }
    }

    private TimerImpl startTimer(TimerName timerName, long startTick) {
        if (currentTimer == null) {
            // this really shouldn't happen as current timer should be non-null unless transaction
            // has completed
            return TimerImpl.createRootTimer(this, (TimerNameImpl) timerName);
        }
        return currentTimer.startNestedTimer(timerName, startTick);
    }

    private @Nullable Object getParentThreadContextDisplay() {
        if (parentTraceEntry == null) {
            return null;
        } else {
            return parentTraceEntry.getThreadContext().hashCode();
        }
    }

    static int getNormalizedStartIndex(StackTraceElement[] locationStackTrace, String methodName,
            int additionalMethodsToSkip) {
        for (int i = 0; i < locationStackTrace.length; i++) {
            if (methodName.equals(locationStackTrace[i].getMethodName())) {
                if (methodName.equals(locationStackTrace[i + 1].getMethodName())
                        && OptionalThreadContextImpl.class.getName()
                                .equals(locationStackTrace[i + 1].getClassName())) {
                    // e.g. OptionalThreadContextImpl.createAuxThreadContext()
                    // -> ThreadContextImpl.createAuxThreadContext()
                    i++;
                }
                return i + 1 + additionalMethodsToSkip;
            }
        }
        return 0;
    }

    // this does not include the root trace entry
    private class DummyTraceEntryOrQuery extends QueryEntryBase implements AsyncQueryEntry, Timer {

        private final TimerImpl syncTimer;
        private final @Nullable AsyncTimer asyncTimer;
        private final long startTick;
        private final Object messageSupplier;

        // not volatile, so depends on memory barrier in Transaction for visibility
        private int selfNestingLevel;
        // only used by transaction thread
        private @Nullable TimerImpl extendedTimer;

        private boolean initialComplete;

        public DummyTraceEntryOrQuery(TimerImpl syncTimer, @Nullable AsyncTimer asyncTimer,
                long startTick, Object messageSupplier, @Nullable QueryData queryData,
                long queryExecutionCount) {
            super(queryData, startTick, queryExecutionCount);
            this.syncTimer = syncTimer;
            this.asyncTimer = asyncTimer;
            this.startTick = startTick;
            this.messageSupplier = messageSupplier;
        }

        @Override
        public void end() {
            endInternal(ticker.read());
        }

        @Override
        public void endWithLocationStackTrace(long threshold, TimeUnit unit) {
            if (threshold < 0) {
                logger.error(
                        "endWithLocationStackTrace(): argument 'threshold' must be non-negative");
            }
            endInternal(ticker.read());
        }

        @Override
        public void endWithError(Throwable t) {
            endWithErrorInternal(null, t);
        }

        @Override
        public void endWithError(@Nullable String message) {
            endWithErrorInternal(message, null);
        }

        @Override
        public void endWithError(@Nullable String message, Throwable t) {
            endWithErrorInternal(message, t);
        }

        @Override
        public void endWithInfo(Throwable t) {
            endInternal(ticker.read());
        }

        private void endWithErrorInternal(@Nullable String message, @Nullable Throwable t) {
            if (initialComplete) {
                // this guards against end*() being called multiple times on async trace entries
                return;
            }
            long endTick = ticker.read();
            endInternal(endTick);
            if (transaction.allowAnotherErrorEntry()) {
                ErrorMessage errorMessage = ErrorMessage.create(message, t,
                        transaction.getThrowableFrameLimitCounter());
                // entry won't be nested properly, but at least the error will get captured
                addErrorEntry(startTick, endTick, messageSupplier, getQueryData(), errorMessage);
            }
        }

        private void endInternal(long endTick) {
            if (initialComplete) {
                // this guards against end*() being called multiple times on async trace entries
                return;
            }
            if (asyncTimer == null) {
                syncTimer.end(endTick);
            } else {
                asyncTimer.end(endTick);
            }
            endQueryData(endTick);
            initialComplete = true;
        }

        @Override
        public Timer extend() {
            if (selfNestingLevel++ == 0) {
                if (isAsync()) {
                    extendAsync();
                } else {
                    TimerImpl currentTimerLocal = currentTimer;
                    if (currentTimerLocal == null) {
                        // thread context has ended, cannot extend sync timer
                        // (this is ok, see https://github.com/glowroot/glowroot/issues/418)
                        selfNestingLevel--;
                        return NopTimer.INSTANCE;
                    }
                    extendSync(ticker.read(), currentTimerLocal);
                }
            }
            return this;
        }

        private void extendSync(long currTick, TimerImpl currentTimer) {
            extendedTimer = syncTimer.extend(currTick, currentTimer);
            extendQueryData(currTick);
        }

        @RequiresNonNull("asyncTimer")
        private void extendAsync() {
            ThreadContextThreadLocal.Holder holder =
                    BytecodeServiceHolder.get().getCurrentThreadContextHolder();
            ThreadContextPlus currThreadContext = holder.get();
            long currTick = ticker.read();
            if (currThreadContext == ThreadContextImpl.this) {
                // this thread context was found in ThreadContextThreadLocal.Holder, so it is still
                // active, and so current timer must be non-null
                extendSync(currTick, checkNotNull(getCurrentTimer()));
            } else {
                // set to null since its value is checked in stopAsync()
                extendedTimer = null;
                extendQueryData(currTick);
            }
            asyncTimer.extend(currTick);
        }

        // this is called for stopping an extension
        @Override
        public void stop() {
            // the timer interface for this class is only expose through return value of extend()
            if (--selfNestingLevel == 0) {
                if (isAsync()) {
                    stopAsync();
                } else {
                    stopSync(ticker.read());
                }
            }
        }

        private void stopSync(long endTick) {
            // the timer interface for this class is only expose through return value of extend()
            checkNotNull(extendedTimer).end(endTick);
            endQueryData(endTick);
        }

        @RequiresNonNull("asyncTimer")
        private void stopAsync() {
            long endTick = ticker.read();
            if (extendedTimer == null) {
                endQueryData(endTick);
                // it is not helpful to capture stack trace at end of async trace entry since it is
                // ended by a different thread (and by not capturing, it reduces thread safety
                // needs)
            } else {
                stopSync(endTick);
            }
            asyncTimer.end(endTick);
        }

        @Override
        public Object getMessageSupplier() {
            return messageSupplier;
        }

        @Override
        public void stopSyncTimer() {
            syncTimer.stop();
        }

        @Override
        public Timer extendSyncTimer(ThreadContext currThreadContext) {
            if (currThreadContext != this) {
                return NopTimer.INSTANCE;
            }
            // this thread context was passed in from plugin, so it is still active, and so current
            // timer must be non-null
            return syncTimer.extend(checkNotNull(getCurrentTimer()));
        }

        @EnsuresNonNullIf(expression = "asyncTimer", result = true)
        private boolean isAsync() {
            return asyncTimer != null;
        }
    }
}


text:
/*!
 RoboToy Explosion Animations
 ©2016 https://github.com/gustavohbf/robotoy
*/
/**
 * Functions used in explosion animations.
 *
 * Depends on:
 * driving_view.js
 * sprites.js
 */

var ROBOTOY = ROBOTOY || {}

ROBOTOY.checkFinishedLoading = ROBOTOY.checkFinishedLoading || (function(){});

ROBOTOY.EXPLOSIONS = {

	explosion : new Array(),
	sprites_explosion_done : false,

	bigexplosion : new Array(),
	sprites_bigexplosion_done : false,

	animating_damage : false

};

ROBOTOY.EXPLOSIONS.loadExplosionSprites = function() {

	var e = ROBOTOY.EXPLOSIONS;

	//e.explosion = loadSeveralImages(0,126,4,'/explosion/explosion','.png');
	loadSpriteOfImages('/explosion.png',126,128,128,11,e.explosion,(function(){
		e.sprites_explosion_done = true;
		ROBOTOY.checkFinishedLoading();
		}));

	//e.bigexplosion = loadSeveralImages(0,238,4,'/bigexplosion/bigexplosion','.png');
	loadSpriteOfImages('/bigexplosion.png',238,128,128,15,e.bigexplosion,(function(){
		e.sprites_bigexplosion_done = true;
		ROBOTOY.checkFinishedLoading();
		}));
}

ROBOTOY.EXPLOSIONS.ExplosionAnimation = function(imgs,x,y,w,h) {
	this.imgs = imgs;
	this.x = x;
	this.y = y;
	this.w = w;
	this.h = h;
	this.count = 0;
	var self = this;

	var container = ROBOTOY.VIEW.container;
	this.layer_explosion = new CanvasLayers.Layer(0, 0, container.getWidth(), container.getHeight());
	container.getChildren().add(this.layer_explosion);
	this.layer_explosion.lowerToBottom();
	this.layer_explosion.onRender = function(layer,rect,ctx) {
		var c = self.count;
		if (c==self.imgs.length)
			return;
		if (!self.imgs[c])
			return;
		if (self.imgs[c].render) {
			self.imgs[c].render(ctx,self.x,self.y,self.w,self.h);
		}
		else if (self.imgs[c].src) {
			ctx.drawImage(self.imgs[c],self.x,self.y,self.w,self.h);
		}
	}

	this.animate = function() {
		if (self.count==self.imgs.length) {
			clearInterval(self.explosion_timer)
			self.layer_explosion.close();
			container.markRectsDamaged(container.getRect())
		}
		else {
			self.count++;
			container.markRectsDamaged();
		}
		container.redraw();
	}
	this.explosion_timer = setInterval(this.animate,5)
};

ROBOTOY.EXPLOSIONS.animateExplosion = function() {
	var e = ROBOTOY.EXPLOSIONS;
	var canvas = ROBOTOY.VIEW.canvas;
	new e.ExplosionAnimation(e.explosion,canvas.width*10/100,canvas.height*10/100,canvas.width*80/100,canvas.height*80/100)
}

ROBOTOY.EXPLOSIONS.animateBigExplosion = function() {
	var e = ROBOTOY.EXPLOSIONS;
	var canvas = ROBOTOY.VIEW.canvas;
	new e.ExplosionAnimation(e.bigexplosion,canvas.width*10/100,canvas.height*10/100,canvas.width*80/100,canvas.height*80/100)
}

ROBOTOY.EXPLOSIONS.flickDamage = function() {
	var e = ROBOTOY.EXPLOSIONS;
	if (e.animating_damage)
		return;
	e.animating_damage = true;
	var container = ROBOTOY.VIEW.container;
	this.layer_damage = new CanvasLayers.Layer(0, 0, container.getWidth(), container.getHeight());
	container.getChildren().add(this.layer_damage);
	this.layer_damage.lowerToBottom();
	this.damage_alpha = 0;
	this.direction_alpha = 1;
	var self = this;
	this.layer_damage.onRender = function(layer,rect,ctx) {
		ctx.fillStyle = 'rgba(250,10,10,'+self.damage_alpha+')';
		ctx.fillRect(0, 0, layer.getWidth(), layer.getHeight());
	}
	this.animate = function() {
		var next_alpha = self.damage_alpha;
		next_alpha += 0.1 * self.direction_alpha;
		if (next_alpha>0.9) {
			self.direction_alpha = -1;
		}
		else if (next_alpha<0.1) {
			self.direction_alpha = 1;
		}
		self.damage_alpha = next_alpha;
		container.markRectsDamaged();
		container.redraw();
	}
	this.damage_timer = setInterval(this.animate,15)
	setTimeout((function(){
		clearInterval(self.damage_timer)
		self.layer_damage.close();
		container.markRectsDamaged(container.getRect())
		container.redraw();
		e.animating_damage = false;
	}),900)
}

redpajama_set_name: RedPajamaGithub


text:
package arrow

import (
	"fmt"
	"io/ioutil"
	"os"

	yaml "gopkg.in/yaml.v2"
)

// Config struct
type Config struct {
	ServerAddress string `yaml:"server,omitempty"`
	LocalAddress  string `yaml:"local,omitempty"`
	Password      string `yaml:"password,omitempty"`
}

// NewConfig factory
func NewConfig(p string) (c *Config) {
	c = &Config{}
	fd, err := os.Open(p)
	defer fd.Close()
	if os.IsNotExist(err) {
		fmt.Fprintln(os.Stderr, "No such file: "+p)
		os.Exit(1)
	}
	checkError(err)

	bytes, err := ioutil.ReadAll(fd)
	checkError(err)

	err = yaml.Unmarshal(bytes, c)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Invalid config: ", err.Error())
		os.Exit(1)
	}
	return
}


text:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ByteTrail.Hex.Core
{
    public class PngImage
    {
        public enum ColorType
        {
            Greyscale = 0,
            TrueColor = 2,
            Indexed = 3,
            GreyscaleAlpha = 4,
            TrueColorAlpha = 6
        }

        public class PngHeader
        {
            public int Width { get; set; }
            public int Height { get; set; }
            public byte BitDepth { get; set; }
            public ColorType ColorType { get; set; }
            public int Dpi { get; set; }
            public float AspectRatio { get; set; }
        }

        private static readonly byte[] HEADER_TAG = { 0x49, 0x48, 0x44, 0x52 };
        private static readonly byte[] PHYSICAL_TAG = { 0x70, 0x48, 0x59, 0x73 };
        private static readonly byte[] SIGNATURE = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };

        private const int TAG_LEN = 4;

        [JsonProperty(PropertyName = "data")]
        private byte[] data;
        [JsonIgnore]
        private PngHeader header;

        /// <summary>
        /// Loads a PNG image from a file identified by the path parameter.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static PngImage Load(string path)
        {
            byte[] buffer = null;
            using (System.IO.FileStream stream = new System.IO.FileStream(path, System.IO.FileMode.Open))
            {
                using (System.IO.BinaryReader reader = new System.IO.BinaryReader(stream))
                {
                    int length = (int)new System.IO.FileInfo(path).Length;
                    buffer = reader.ReadBytes((int)length);
                }
            }
            PngImage image = new PngImage(buffer, false);
            return image;
        }

        [JsonIgnore]
        public byte[] Data
        {
            set
            {
                if (!IsPngFile(value))
                {
                    throw new ArgumentException("Invalid PNG data");
                }
                data = value;
            }
            get
            {
                return data;
            }
        }

        [JsonIgnore]
        public PngHeader Header
        {
            get
            {
                int idx = 0;
                if (header == null)
                {
                    header = new PngHeader();
                    idx = GetChunkStart(HEADER_TAG);
                    header.Width = Int32FromArray(data, idx);
                    idx += 4;
                    header.Height = Int32FromArray(data, idx);
                    idx += 4;
                    header.BitDepth = data[idx++];
                    header.ColorType = (ColorType)Enum.ToObject(typeof(ColorType), data[idx++]);
                }
                // get the physical dimensions information
                idx = GetChunkStart(PHYSICAL_TAG);
                int dpmX = Int32FromArray(data, idx);
                idx += 4;
                int dpmY = Int32FromArray(data, idx);
                idx += 4;
                bool isMeter = data[idx] == 1;
                if(isMeter)
                {
                    header.Dpi = (int)(dpmX / 39.37);
                }
                header.AspectRatio = dpmX / dpmY;
                return header;
            }
        }

        public PngImage()
        {

        }

        public PngImage(byte[] pngData, bool copy = false)
        {
            if (!IsPngFile(pngData))
            {
                throw new ArgumentException("Invalid PNG data");
            }
            else
            {
                if (copy)
                {
                    data = new byte[pngData.Length];
                    System.Array.Copy(pngData, data, pngData.Length);
                }
                else
                {
                    data = pngData;
                }
            }
        }

        /// <summary>
        /// Determines if is png file the specified data.
        /// </summary>
        /// <returns><c>true</c> if is png file the specified data; otherwise, <c>false</c>.</returns>
        /// <param name="data">PNG Data</param>
        public static bool IsPngFile(byte[] data)
        {
            bool result = true;
            // check the PNG signature
            for (int i = 0; i < SIGNATURE.Length; i++)
            {
                if (data[i] != SIGNATURE[i])
                {
                    // the passed array is not a valid PNG file
                    result = false;
                    break;
                }
            }
            return result;
        }

        private int GetChunkStart(byte[] chunkHeader)
        {
            int hdx = 0;
            int index = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (data[i] == chunkHeader[hdx])
                {
                    hdx++;
                }
                else
                {
                    hdx = 0;
                }
                // check header identified
                if (hdx == TAG_LEN)
                {
                    index = i + 1;
                    break;
                }
            }
            return index;
        }

        /// <summary>
        /// Creates an Int32 from array of data. The array is assumed to hold an int in network byte order.
        /// </summary>
        /// <returns>The from array.</returns>
        /// <param name="data">Data.</param>
        /// <param name="idx">Index.</param>
        private Int32 Int32FromArray(byte[] data, int idx)
        {
            Int32 value = 0;

            value = (data[idx] << 32) + (data[idx + 1] << 16) + (data[idx + 2] << 8) + data[idx + 3];
            return value;
        }
    }
}


text:
Thanks for contributing to libphonenumber!

Please read the following before filing an issue or sending a pull request.

We hope these guidelines will enhance your experience as a contributor to our
library and know that we appreciate the time you put into making it better.

## Pull requests

We do not accept pull requests for validation, formatting, or timezone metadata
updates.

For changes specific to windows builds, see [Filing a code
issue](#filing-a-code-issue) and make sure you have found a reviewer and tester
before sending the pull request.

We are happy to review and accept pull requests for the following:

*   Carrier updates
*   Geocoding updates
*   Bug fixes
*   Documentation and code hygiene cleanups

This list is not exhaustive. To clarify whether we'd accept a pull request, and
especially before spending significant time on one such as for a bug fix, we
strongly encourage that you bring up the question on an issue.

To get your pull request merged, we need the following:

*   A CLA signature. See below.
*   Responsiveness to back and forth review comments, because we will do a code
    review.
*   A link to a clear description of what the pull request intends to solve in a
    [GitHub issue](https://github.com/googlei18n/libphonenumber/issues/new) or
    Google's [Issue
    Tracker](http://issuetracker.google.com/issues/new?component=192347).
*   Tests that illustrate the issue, if applicable.
*   Willingness and ability to implement the changes in C++, Java, and JS if
    applicable. For example, changes to `PhoneNumberUtil.java` must be ported to
    `phonenumberutil.cc` and `phonenumberutil.js`.
    *   The initial pull request may contain the implementation in only one
        language to get approval on the approach.

If this is not possible, please file an issue instead.

## Checklist before filing an issue

Please check the following:
*   Has the issue already been discussed in the
    [issues](http://github.com/googlei18n/libphonenumber/issues) or [discussion
    group](https://groups.google.com/group/libphonenumber-discuss)? If so, you
    may want to comment on an existing discussion.
*   Is the issue reproducible using the
    [demo](http://libphonenumber.appspot.com/)? If not:
    *   Your issue may be resolved by upgrading to the latest version of the
        library.
    *   If you are using a
        [port](http://github.com/googlei18n/libphonenumber#third-party-ports),
        issues should be reported against that project.
    *   If you are using the library through a front-end or wrapper, issues
        should be reported against that project.

## Filing a metadata issue

Please copy this template into your report and answer the questions to the best of your ability.
For acceptable evidence, [see below](#provide-supporting-evidence).

``` nomarkdown
*   Country:
*   Example number(s) and/or range(s):
*   Number type ("fixed-line", "mobile", "short code", etc.):
*   For short codes, cost and dialing restrictions:
*   Where or whom did you get the number(s) from:
*   Authoritative evidence (e.g. national numbering plan, operator announcement):
*   Link from demo (http://libphonenumber.appspot.com) showing error:
```

For issues affecting validation, formatting, or other aspects covered by the metadata,
we invite you to file issues in Google's new [Issue Tracker](http://issuetracker.google.com/issues/new?component=192347),
which we're currently testing.

### Provide authoritative evidence

Ideally, change requests for ranges should be accompanied by authoritative
evidence such as official government or public carrier documents.

If the evidence is publicly available online, please provide the link.

If the evidence is not publicly available online, make sure that you have the
rights to share this with us, and confirm this by reading and signing the
appropriate Contributor License Agreement (CLA).

See https://cla.developers.google.com/about to determine whether you need to
sign a Corporate or Individual CLA.

**By signing the CLA, you confirm that you have the rights to share the
information with us, and that we may use, modify, reproduce, publicly display,
and distribute the information in accordance with the library's [open source
license](http://github.com/googlei18n/libphonenumber/blob/master/LICENSE).**

*   [Corporate CLA](http://developers.google.com/open-source/cla/corporate?csw=1):
    *   See https://cla.developers.google.com/about and follow the instructions.
    *   Once you are all set up, either create a validation issue for your
        request, or go to the relevant open issue.
    *   Comment on the issue, using the GitHub account that's already set up for
        your Corporate CLA, with "I signed the CLA."
    *   If you're set up correctly, someone from the team will update you on the
        issue, with instructions for sending private documentation to our closed
        mailing list. Only the core libphonenumber team has access to view
        emails sent to this address.

*   [Individual CLA](http://cla.developers.google.com/about/google-individual?csw=1):
    *   See https://cla.developers.google.com/about to ensure that an Individual
        CLA is what you need to sign, and for help with troubleshooting.
    *   When signing the Individual CLA, use the same GitHub username you used
        (or will use) to file the corresponding issue.
    *   If the email address you use in the Individual CLA is not already
        associated with that GitHub account, [add
        it](https://help.github.com/articles/adding-an-email-address-to-your-github-account/).
    *   If you need to modify an Individual CLA signature, such as to change the
        GitHub username, go to https://cla.developers.google.com/clas and click
        on "Edit Contact Information".
    *   Once you are all set up, either create a validation issue for your
        request, or go to the relevant open issue.
    *   Comment on the issue, using the GitHub account that's already set up for
        your Individual CLA, with "I signed the CLA."
    *   If you're set up correctly, someone from the team will update you on the
        issue, with instructions for sending private documentation to our closed
        mailing list. Only the core libphonenumber team has access to view
        emails sent to this address.

## Filing a code issue

When filing a code issue, include the specifics of your operating system and
provide as much information as possible that helps us reproduce the problem.

Please be advised that metadata updates are prioritized over code changes,
except for bug fixes. In addition, we work with a limited number of build
systems and may not be able to support every setup.

In particular, we don't actively maintain windows builds but would be able to
accept a PR provided someone else in the open-source community could test it out
and would be able to help with the review. One way to look for such
collaborators would be to email the [discussion
group](https://groups.google.com/group/libphonenumber-discuss). Also see the
[known Windows issues](FAQ.md#what-about-windows).


text: export {default} from './WrapUpStoryView';


text:
package cookbook.json_libraries

case class Profile(name: String, age: Option[Int])

// fintrospect-core
// fintrospect-circe
object Full_Auto_Marshalling_Example extends App {

  import com.twitter.finagle.http.Method.Post
  import com.twitter.finagle.http.path.Root
  import com.twitter.finagle.http.{Request, Response}
  import com.twitter.finagle.{Http, Service}
  import com.twitter.util.Await.ready
  import com.twitter.util.Future
  import io.circe.generic.auto._
  import io.fintrospect.formats.Circe
  import io.fintrospect.formats.Circe.Auto._
  import io.fintrospect.parameters.Body
  import io.fintrospect.{Module, RouteModule, RouteSpec, ServerRoute}

  val insultMe: Service[Profile, Profile] = Service.mk[Profile, Profile] {
    inProfile => Future(inProfile.copy(name = inProfile.name + " Smells"))
  }

  val route: ServerRoute[Request, Response] = RouteSpec()
    .body(Body.of(Circe.bodySpec[Profile]()))
    .at(Post) bindTo InOut(insultMe)

  val module: Module = RouteModule(Root).withRoute(route)

  ready(Http.serve(":9999", module.toService))
}

//curl -v -XPOST http://localhost:9999/ --data '{"name":"David", "age": 50}'


text:
SPEC_BEGIN(ExampleSpec)

//
describe(@"Example", ^{

  it(@"add: should add two numbers together", ^{
    [[[Example add:@1 y:@2] should] equal:@3];
  });

  it(@"concatenate: should concatenate two strings", ^{
    [[[Example concatenate:@"Hello" y:@" World"] should] equal:@"Hello World"];
  });

});

SPEC_END


text:
<!DOCTYPE html>
<html>
<head>
  <title>Module</title>
</head>
<body>
  <script src="/dist/bundle.js"></script>
  <script>
    // test or demo module here
  </script>
</body>
</html>


text:
/* ###
 * IP: GHIDRA
 *
 * 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.
 */
/*
 * Created on Feb 7, 2005
 *
 */
package ghidra.app.plugin.processors.sleigh.pattern;

import ghidra.app.plugin.processors.sleigh.ParserWalker;
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.StringUtilities;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;

/**
 *
 *
 * Matches against the actual instruction bit stream
 */
public class InstructionPattern extends DisjointPattern {

	private PatternBlock maskvalue;

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
	 */
	@Override
	public PatternBlock getBlock(boolean context) {
		return context ? null : maskvalue;
	}

	public InstructionPattern() {
		maskvalue = null;
	}

	public InstructionPattern(PatternBlock mv) {
		maskvalue = mv;
	}

	public InstructionPattern(boolean tf) {
		maskvalue = new PatternBlock(tf);
	}

	public PatternBlock getBlock() {
		return maskvalue;
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
	 */
	@Override
	public Pattern simplifyClone() {
		return new InstructionPattern((PatternBlock) maskvalue.clone());
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction()
	 */
	@Override
	public void shiftInstruction(int sa) {
		maskvalue.shift(sa);
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
	 */
	@Override
	public Pattern doOr(Pattern b, int sa) {
		if (b.numDisjoint() > 0)
			return b.doOr(this, -sa);

		if (b instanceof CombinePattern)
			return b.doOr(this, -sa);

		DisjointPattern res1, res2;
		res1 = (DisjointPattern) simplifyClone();
		res2 = (DisjointPattern) b.simplifyClone();
		if (sa < 0)
			res1.shiftInstruction(-sa);
		else
			res2.shiftInstruction(sa);
		return new OrPattern(res1, res2);
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
	 */
	@Override
	public Pattern doAnd(Pattern b, int sa) {
		if (b.numDisjoint() > 0)
			return b.doAnd(this, -sa);
		if (b instanceof CombinePattern)
			return b.doAnd(this, -sa);
		if (b instanceof ContextPattern) {
			InstructionPattern newpat = (InstructionPattern) simplifyClone();
			if (sa < 0)
				newpat.shiftInstruction(-sa);
			return new CombinePattern((ContextPattern) b.simplifyClone(), newpat);
		}
		// b must be an InstructionPattern if it reaches here
		PatternBlock respattern;
		if (sa < 0) {
			PatternBlock a = (PatternBlock) maskvalue.clone();
			a.shift(-sa);
			respattern = a.andBlock(((InstructionPattern) b).maskvalue);
		}
		else {
			PatternBlock c = (PatternBlock) ((InstructionPattern) b).maskvalue.clone();
			c.shift(sa);
			respattern = maskvalue.andBlock(c);
		}
		return new InstructionPattern(respattern);
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
	 */
	@Override
	public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
			throws MemoryAccessException {
		boolean match = maskvalue.isInstructionMatch(walker);
		debugPatternMatch(debug, walker, match);
		return match;
	}

	private void debugPatternMatch(SleighDebugLogger debug, ParserWalker walker, boolean match) {
		if (debug == null) {
			return;
		}
		debug.append("byte pattern: ");
		if (alwaysTrue()) {
			debug.append("always-Matched\n");
		}
		else if (alwaysFalse()) {
			debug.append("always-Failed\n");
		}
		else {
			MemBuffer memBuf = walker.getParserContext().getMemBuffer();
			int offset = walker.getOffset(-1) + maskvalue.offset;
			int byteCnt = maskvalue.maskvec.length * 4;
			byte[] bytes = new byte[byteCnt];
			memBuf.getBytes(bytes, offset);

			if (match) {
				debug.addInstructionPattern(offset, maskvalue);
			}

			if (debug.isVerboseEnabled()) {
				debug.append("mask=");
				debug.append(maskvalue.maskvec, -1, 0);
				debug.append("\n");
				int endoffset = offset + bytes.length - 1;
				String leader = "bytes[" + offset + "-" + endoffset + "]=";
				debug.append(StringUtilities.pad(leader, ' ', 19));
				debug.append(bytes, -1, 0);
				debug.append("\n");
				debug.append("       match-value=");
				debug.append(maskvalue.valvec, -1, 0);
				debug.append(" " + (match ? "Matched" : "Failed") + "\n");
			}
		}
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
	 */
	@Override
	public boolean alwaysTrue() {
		return maskvalue.alwaysTrue();
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
	 */
	@Override
	public boolean alwaysFalse() {
		return maskvalue.alwaysFalse();
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
	 */
	@Override
	public boolean alwaysInstructionTrue() {
		return maskvalue.alwaysTrue();
	}

	/* (non-Javadoc)
	 * @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
	 */
	@Override
	public void restoreXml(XmlPullParser parser) {
		XmlElement el = parser.start("instruct_pat");
		maskvalue = new PatternBlock(true);
		maskvalue.restoreXml(parser);
		parser.end(el);
	}

	@Override
	public String toString() {
		if (alwaysTrue()) {
			return "always";
		}
		if (alwaysFalse()) {
			return "never";
		}
		return "ins:" + maskvalue;
	}
}


text:
#ifndef FLAC__TEST_LIBFLACPP_METADATA_H
#define FLAC__TEST_LIBFLACPP_METADATA_H

bool test_metadata();

#endif


text:
<?xml version="1.0" encoding="UTF-8"?><concept xmlns="http://www.w3.org/2004/02/skos/core#">
      <prefLabel>END STAGE RENAL DISEASE TREATMENT FACILITY</prefLabel>
      <definition>A facility, other than a hospital, which provides dialysis treatment, maintenance,
         and/or training to patients or caregivers on an ambulatory or home-care basis.</definition>
   </concept>


text:
import stampit from '../ext/stampit';
import cuid from 'cuid';

const Unique = stampit({
  init () {
    const id = this.id || cuid();
    Object.defineProperty(this, 'id', {
      value: id,
      configurable: true,
      writable: false,
      enumerable: true
    });
  }
});

export default Unique;


text:
<?php
namespace Robo\Common;

trait ProgressIndicatorAwareTrait
{
    use Timer;

    /**
     * @var null|\Robo\Common\ProgressIndicator
     */
    protected $progressIndicator;

    /**
     * @return int
     */
    public function progressIndicatorSteps()
    {
        return 0;
    }

    /**
     * @param null|\Robo\Common\ProgressIndicator $progressIndicator
     */
    public function setProgressIndicator($progressIndicator)
    {
        $this->progressIndicator = $progressIndicator;
    }

    /**
     * @return null|bool
     */
    protected function hideProgressIndicator()
    {
        if (!$this->progressIndicator) {
            return;
        }
        return $this->progressIndicator->hideProgressIndicator();
    }

    protected function showProgressIndicator()
    {
        if (!$this->progressIndicator) {
            return;
        }
        $this->progressIndicator->showProgressIndicator();
    }

    /**
     * @param bool $visible
     */
    protected function restoreProgressIndicator($visible)
    {
        if (!$this->progressIndicator) {
            return;
        }
        $this->progressIndicator->restoreProgressIndicator($visible);
    }

    /**
     * @return int
     */
    protected function getTotalExecutionTime()
    {
        if (!$this->progressIndicator) {
            return 0;
        }
        return $this->progressIndicator->getExecutionTime();
    }

    protected function startProgressIndicator()
    {
        $this->startTimer();
        if (!$this->progressIndicator) {
            return;
        }
        $totalSteps = $this->progressIndicatorSteps();
        $this->progressIndicator->startProgressIndicator($totalSteps, $this);
    }

    /**
     * @return bool
     */
    protected function inProgress()
    {
        if (!$this->progressIndicator) {
            return false;
        }
        return $this->progressIndicator->inProgress();
    }

    protected function stopProgressIndicator()
    {
        $this->stopTimer();
        if (!$this->progressIndicator) {
            return;
        }
        $this->progressIndicator->stopProgressIndicator($this);
    }

    protected function disableProgressIndicator()
    {
        $this->stopTimer();
        if (!$this->progressIndicator) {
            return;
        }
        $this->progressIndicator->disableProgressIndicator();
    }

    protected function detatchProgressIndicator()
    {
        $this->setProgressIndicator(null);
    }

    /**
     * @param int $steps
     */
    protected function advanceProgressIndicator($steps = 1)
    {
        if (!$this->progressIndicator) {
            return;
        }
        $this->progressIndicator->advanceProgressIndicator($steps);
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
	android:background="#ff000000"
    android:id="@+id/createController">

    <EditText
        android:id="@+id/createControllerName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Name"
        android:inputType="text" />

    <EditText
        android:id="@+id/createControllerIp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter IP Address"
        android:inputType="text" />

    <Button
        android:id="@+id/createControllerColor"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/createControllerColor"/>
    <Button
        android:id="@+id/createControllerSubmit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/createControllerSubmit"/>"

    <Button
        android:id="@+id/createControllerClose"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/createControllerClose"/>
</LinearLayout>


text:
class AttachmentUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  include CarrierWave::MimeTypes

  # Choose what kind of storage to use for this uploader:
  storage Rails.application.config.carrierwave_storage

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/paper/#{model.paper.id}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  version :detail do
    process resize_to_limit: [986, -1]
  end

  version :preview do
    process :convert_to_png, if: :needs_transcoded?
    process resize_to_limit: [475, 220]

    def full_filename(orig_file)
      if needs_transcoded?(orig_file)
        "#{version_name}_#{File.basename(orig_file, ".*")}.png"
      else
        "#{version_name}_#{orig_file}"
      end
    end
  end

  private

  def convert_to_png
    manipulate! do |image|
      image.format("png")
      image
    end
    file.content_type = "image/png"
  end

  def needs_transcoded?(file)
    # On direct upload, the file's content_type is application/octet-stream, so
    # we also need to check the filename
    if file.respond_to?('content_type')
      ["image/tiff", "application/postscript"].include?(file.content_type)
    else
      !!(File.extname(file) =~ /(tif?f|eps)/i)
    end
  end
end


text:
<!DOCTYPE html>

  <title> Binary Tree Count Value Exercise</title>

  <link rel="stylesheet" href="../../lib/codemirror/lib/codemirror.css">

Write a recursive function that
      returns the number of times that the given value appears in the
      binary tree pointed at by "root".

    <textarea  id="codeTextarea">
int btCntVal(BinNode root, Comparable value) {
  // Your code goes between these lines

  // Your code goes between these lines

}
</textarea>

 [ editor.getValue()  ]

	     window.codeValue = editor.getValue();
         window.progexType= "binarytree";
         window.summexName= "btCntValPROG";


text:
<?php namespace Exolnet\Cache;

use Illuminate\Filesystem\Filesystem;

class Bust
{
	/**
	 * @var \Illuminate\Filesystem\Filesystem
	 */
	private $filesystem;

	/**
	 * @var bool
	 */
	protected $enabled = true;

	/**
	 * Bust constructor.
	 *
	 * @param \Illuminate\Filesystem\Filesystem $filesystem
	 */
	public function __construct(Filesystem $filesystem)
	{

		$this->filesystem = $filesystem;
	}

	/**
	 * @return bool
	 */
	public function isEnabled()
	{
		return $this->enabled;
	}

	/**
	 * @param bool $enabled
	 * @return $this
	 */
	public function setEnabled($enabled)
	{
		$this->enabled = (bool)$enabled;

		return $this;
	}

	/**
	 * Generate an asset path for the application with the file's last modification timestamp
	 * to avoid cashing.
	 *
	 * @param  string    $path
	 * @param  bool|null $secure
	 * @return string
	 */
	public function asset($path, $secure = null)
	{
		if ( ! $this->isEnabled()) {
			return asset($path, $secure);
		}

		$uri = $this->path($path);

		return asset($uri, $secure);
	}

	/**
	 * @param string $path
	 * @return string
	 */
	public function path($path)
	{
		if ( ! $this->isEnabled()) {
			return $path;
		}

		$fullPath = public_path() . '/' . $path;

		if ( ! $this->filesystem->exists($fullPath)) {
			return $path;
		}

		$time = $this->filesystem->lastModified($fullPath);

		if ( ! $time) {
			return $path;
		}

		$basename = pathinfo($path, PATHINFO_BASENAME);
		$pos = strrpos($basename, '.');

		if ($pos === false) {
			return $path;
		}

		$basename_bust = substr($basename, 0, $pos) . '.' . $time . substr($basename, $pos);
		return substr($path, 0, -strlen($basename)) . $basename_bust;
	}

	/**
	 * @param string $path
	 * @return string
	 */
	public function filename($path)
	{
		return basename($this->path($path));
	}
}


text:
package net.dv8tion.jda.internal.handle;

import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
import net.dv8tion.jda.api.hooks.VoiceDispatchInterceptor;
import net.dv8tion.jda.api.utils.MiscUtil;
import net.dv8tion.jda.api.utils.data.DataObject;
import net.dv8tion.jda.internal.JDAImpl;
import net.dv8tion.jda.internal.audio.AudioConnection;
import net.dv8tion.jda.internal.managers.AudioManagerImpl;
import net.dv8tion.jda.internal.requests.WebSocketClient;

public class VoiceServerUpdateHandler extends SocketHandler
{
    public VoiceServerUpdateHandler(JDAImpl api)
    {
        super(api);
    }

    @Override
    protected Long handleInternally(DataObject content)
    {
        final long guildId = content.getLong("guild_id");
        if (getJDA().getGuildSetupController().isLocked(guildId))
            return guildId;
        Guild guild = getJDA().getGuildById(guildId);
        if (guild == null)
            throw new IllegalArgumentException("Attempted to start audio connection with Guild that doesn't exist!");

        getJDA().getDirectAudioController().update(guild, guild.getSelfMember().getVoiceState().getChannel());

        if (content.isNull("endpoint"))
        {
            //Discord did not provide an endpoint yet, we are to wait until discord has resources to provide
            // an endpoint, which will result in them sending another VOICE_SERVER_UPDATE which we will handle
            // to actually connect to the audio server.
            return null;
        }

        //Strip the port from the endpoint.
        String endpoint = content.getString("endpoint").replace(":80", "");
        String token = content.getString("token");
        String sessionId = guild.getSelfMember().getVoiceState().getSessionId();
        if (sessionId == null)
            throw new IllegalArgumentException("Attempted to create audio connection without having a session ID. Did VOICE_STATE_UPDATED fail?");

        VoiceDispatchInterceptor voiceInterceptor = getJDA().getVoiceInterceptor();
        if (voiceInterceptor != null)
        {
            voiceInterceptor.onVoiceServerUpdate(new VoiceDispatchInterceptor.VoiceServerUpdate(guild, endpoint, token, sessionId, allContent));
            return null;
        }

        AudioManagerImpl audioManager = (AudioManagerImpl) getJDA().getAudioManagersView().get(guildId);
        if (audioManager == null)
        {
            WebSocketClient.LOG.debug(
                "Received a VOICE_SERVER_UPDATE but JDA is not currently connected nor attempted to connect " +
                "to a VoiceChannel. Assuming that this is caused by another client running on this account. " +
                "Ignoring the event.");
            return null;
        }

        MiscUtil.locked(audioManager.CONNECTION_LOCK, () ->
        {
            //Synchronized to prevent attempts to close while setting up initial objects.
            AudioChannel target = guild.getSelfMember().getVoiceState().getChannel();
            if (target == null)
            {
                WebSocketClient.LOG.warn("Ignoring VOICE_SERVER_UPDATE for unknown channel");
                return;
            }

            AudioConnection connection = new AudioConnection(audioManager, endpoint, sessionId, token, target);
            audioManager.setAudioConnection(connection);
            connection.startConnection();
        });
        return null;
    }
}


text:
package gui;

import javax.swing.*;
import java.awt.*;
import java.util.Hashtable;

public class TemperatureMap extends Hashtable<Integer, JLabel>
{
	private JLabel lblNegative150;
	private JLabel lblNegative100;
	private JLabel lblNegative50;

	private JLabel lblZero;

	private JLabel lblPositive50;
	private JLabel lblPositive100;
	private JLabel lblPositive150;

	public TemperatureMap()
    {
        initLabelValues();
        styleLabels();
		buildLabelTable();
	}

    private void initLabelValues()
    {
        lblNegative150 = new JLabel("-150");
		lblNegative100 = new JLabel("-100");
		lblNegative50 = new JLabel("-50");

		lblZero = new JLabel("0");

		lblPositive50 = new JLabel("50");
		lblPositive100 = new JLabel("100");
		lblPositive150 = new JLabel("150");
    }

    private void styleLabels()
    {
        Font font = new Font("Courier",Font.BOLD, 10);

		lblNegative150.setFont(font);
		lblNegative150.setForeground(Color.red);
		lblNegative100.setFont(font);
		lblNegative100.setForeground(Color.red);
		lblNegative50.setFont(font);
		lblNegative50.setForeground(Color.red);

		lblZero.setFont(font);
		lblZero.setForeground(Color.blue);

		lblPositive50.setFont(font);
		lblPositive50.setForeground(Color.yellow);
		lblPositive100.setFont(font);
		lblPositive100.setForeground(Color.yellow);
		lblPositive150.setFont(font);
		lblPositive150.setForeground(Color.yellow);
    }

	private void buildLabelTable()
    {
		put(-150, lblNegative150);
		put(-100, lblNegative100);
		put(-50, lblNegative50);

        put(0, lblZero);

        put(50, lblPositive50);
		put(100, lblPositive100);
		put(150, lblPositive150);
	}
}