text:
class GCConfigStringHolder
{
private:
    const char* m_str;

public:
    // Constructs a new GCConfigStringHolder around a string obtained from
    // GCToEEInterface::GetStringConfigValue.
    explicit GCConfigStringHolder(const char* str)
      : m_str(str) {}

    // No copy operators - this type cannot be copied.
    GCConfigStringHolder(const GCConfigStringHolder&) = delete;
    GCConfigStringHolder& operator=(const GCConfigStringHolder&) = delete;

    // This type is returned by-value by string config functions, so it
    // requires a move constructor.
    GCConfigStringHolder(GCConfigStringHolder&&) = default;

    // Frees a string config value by delegating to GCToEEInterface::FreeStringConfigValue.
    ~GCConfigStringHolder()
    {
        if (m_str)
        {
            GCToEEInterface::FreeStringConfigValue(m_str);
        }

        m_str = nullptr;
    }

    // Retrieves the wrapped config string.
    const char* Get() const { return m_str; }
};

// Each one of these keys produces a method on GCConfig with the name "Get{name}", where {name}
// is the first parameter of the *_CONFIG macros below.
#define GC_CONFIGURATION_KEYS \
  BOOL_CONFIG(ServerGC,     "gcServer",     false, "Whether we should be using Server GC")     \
  BOOL_CONFIG(ConcurrentGC, "gcConcurrent", true,  "Whether we should be using Concurrent GC") \
  BOOL_CONFIG(ConservativeGC, "gcConservative", false, "Enables/Disables conservative GC")     \
  BOOL_CONFIG(ForceCompact, "gcForceCompact", false,                                           \
      "When set to true, always do compacting GC")                                             \
  BOOL_CONFIG(RetainVM,     "GCRetainVM",   false,                                             \
      "When set we put the segments that should be deleted on a standby list (instead of "     \
      "releasing them back to the OS) which will be considered to satisfy new segment requests"\
     " (note that the same thing can be specified via API which is the supported way)")        \
  BOOL_CONFIG(StressMix,    "GCStressMix",  false,                                             \
      "Specifies whether the GC mix mode is enabled or not")                                   \
  BOOL_CONFIG(BreakOnOOM,   "GCBreakOnOOM", false,                                             \
      "Does a DebugBreak at the soonest time we detect an OOM")                                \
  BOOL_CONFIG(NoAffinitize, "GCNoAffinitize", false,                                           \
      "If set, do not affinitize server GC threads")                                           \
  BOOL_CONFIG(LogEnabled,   "GCLogEnabled", false,                                             \
      "Specifies if you want to turn on logging in GC")                                        \
  BOOL_CONFIG(ConfigLogEnabled, "GCConfigLogEnabled", false,                                   \
      "Specifies the name of the GC config log file")                                          \
  BOOL_CONFIG(GCNumaAware,   "GCNumaAware", true, "Enables numa allocations in the GC")        \
  BOOL_CONFIG(GCCpuGroup,    "GCCpuGroup", false, "Enables CPU groups in the GC")              \
  INT_CONFIG(HeapVerifyLevel, "HeapVerify", HEAPVERIFY_NONE,                                   \
      "When set verifies the integrity of the managed heap on entry and exit of each GC")      \
  INT_CONFIG(LOHCompactionMode, "GCLOHCompact", 0, "Specifies the LOH compaction mode")        \
  INT_CONFIG(LOHThreshold, "GCLOHThreshold", LARGE_OBJECT_SIZE,                                \
      "Specifies the size that will make objects go on LOH")                                   \
  INT_CONFIG(BGCSpinCount,  "BGCSpinCount", 140, "Specifies the bgc spin count")               \
  INT_CONFIG(BGCSpin,       "BGCSpin",      2,   "Specifies the bgc spin time")                \
  INT_CONFIG(HeapCount,     "GCHeapCount",  0,   "Specifies the number of server GC heaps")    \
  INT_CONFIG(Gen0Size,      "GCgen0size",   0, "Specifies the smallest gen0 size")             \
  INT_CONFIG(SegmentSize,   "GCSegmentSize", 0, "Specifies the managed heap segment size")     \
  INT_CONFIG(LatencyMode,   "GCLatencyMode", -1,                                               \
      "Specifies the GC latency mode - batch, interactive or low latency (note that the same " \
      "thing can be specified via API which is the supported way")                             \
  INT_CONFIG(LatencyLevel,  "GCLatencyLevel", 1,                                               \
      "Specifies the GC latency level that you want to optimize for. Must be a number from 0"  \
      "3. See documentation for more details on each level.")                                  \
  INT_CONFIG(LogFileSize,   "GCLogFileSize", 0, "Specifies the GC log file size")              \
  INT_CONFIG(CompactRatio,  "GCCompactRatio", 0,                                               \
      "Specifies the ratio compacting GCs vs sweeping")                                        \
  INT_CONFIG(GCHeapAffinitizeMask, "GCHeapAffinitizeMask", 0,                                  \
      "Specifies processor mask for Server GC threads")                                        \
  INT_CONFIG(GCHighMemPercent, "GCHighMemPercent", 0,                                          \
      "The percent for GC to consider as high memory")                                         \
  INT_CONFIG(GCProvModeStress, "GCProvModeStress", 0,                                          \
      "Stress the provisional modes")                                                          \
  INT_CONFIG(GCGen0MaxBudget, "GCGen0MaxBudget", 0,                                            \
      "Specifies the largest gen0 allocation budget")                                          \
  INT_CONFIG(GCHeapHardLimit, "GCHeapHardLimit", 0,                                            \
      "Specifies a hard limit for the GC heap")                                                \
  INT_CONFIG(GCHeapHardLimitPercent, "GCHeapHardLimitPercent", 0,                              \
      "Specifies the GC heap usage as a percentage of the total memory")                       \
  STRING_CONFIG(LogFile,    "GCLogFile",    "Specifies the name of the GC log file")           \
  STRING_CONFIG(ConfigLogFile, "GCConfigLogFile",                                              \
      "Specifies the name of the GC config log file")                                          \
  STRING_CONFIG(MixLogFile, "GCMixLog",                                                        \
      "Specifies the name of the log file for GC mix statistics")

// This class is responsible for retreiving configuration information
// for how the GC should operate.
class GCConfig
{
#define BOOL_CONFIG(name, unused_key, unused_default, unused_doc) \
  public: static bool Get##name();                                \
  private: static bool s_##name;
#define INT_CONFIG(name, unused_key, unused_default, unused_doc) \
  public: static int64_t Get##name();                            \
  private: static int64_t s_##name;
#define STRING_CONFIG(name, unused_key, unused_doc) \
  public: static GCConfigStringHolder Get##name();
GC_CONFIGURATION_KEYS
#undef BOOL_CONFIG
#undef INT_CONFIG
#undef STRING_CONFIG

public:
// Flags that may inhabit the number returned for the HeapVerifyLevel config option.
// Keep this in sync with vm\eeconfig.h if this ever changes.
enum HeapVerifyFlags {
    HEAPVERIFY_NONE             = 0,
    HEAPVERIFY_GC               = 1,   // Verify the heap at beginning and end of GC
    HEAPVERIFY_BARRIERCHECK     = 2,   // Verify the brick table
    HEAPVERIFY_SYNCBLK          = 4,   // Verify sync block scanning

    // the following options can be used to mitigate some of the overhead introduced
    // by heap verification.  some options might cause heap verifiction to be less
    // effective depending on the scenario.

    HEAPVERIFY_NO_RANGE_CHECKS  = 0x10,   // Excludes checking if an OBJECTREF is within the bounds of the managed heap
    HEAPVERIFY_NO_MEM_FILL      = 0x20,   // Excludes filling unused segment portions with fill pattern
    HEAPVERIFY_POST_GC_ONLY     = 0x40,   // Performs heap verification post-GCs only (instead of before and after each GC)
    HEAPVERIFY_DEEP_ON_COMPACT  = 0x80    // Performs deep object verfication only on compacting GCs.
};

// Initializes the GCConfig subsystem. Must be called before accessing any
// configuration information.
static void Initialize();

};

#endif // __GCCONFIG_H__


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

package com.google.firebase.crashlytics.internal.persistence;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.firebase.crashlytics.internal.Logger;
import com.google.firebase.crashlytics.internal.common.CrashlyticsReportWithSessionId;
import com.google.firebase.crashlytics.internal.metadata.UserMetadata;
import com.google.firebase.crashlytics.internal.model.CrashlyticsReport;
import com.google.firebase.crashlytics.internal.model.CrashlyticsReport.Session;
import com.google.firebase.crashlytics.internal.model.CrashlyticsReport.Session.Event;
import com.google.firebase.crashlytics.internal.model.ImmutableList;
import com.google.firebase.crashlytics.internal.model.serialization.CrashlyticsReportJsonTransform;
import com.google.firebase.crashlytics.internal.settings.SettingsProvider;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This class handles persisting report and event data to disk, combining reports with their
 * associated events into "finalized" report files, reading reports from disk, parsing them to be
 * returned as CrashlyticsReport objects, and deleting them.
 */
public class CrashlyticsReportPersistence {

  private static final Charset UTF_8 = Charset.forName("UTF-8");

  private static final int MAX_OPEN_SESSIONS = 8;

  private static final String REPORT_FILE_NAME = "report";
  // We use the lastModified timestamp of this file to quickly store and access the startTime in ms
  // of a session.
  private static final String SESSION_START_TIMESTAMP_FILE_NAME = "start-time";
  private static final String EVENT_FILE_NAME_PREFIX = "event";
  private static final int EVENT_COUNTER_WIDTH = 10; // String width of maximum positive int value
  private static final String EVENT_COUNTER_FORMAT = "%0" + EVENT_COUNTER_WIDTH + "d";
  private static final int EVENT_NAME_LENGTH =
      EVENT_FILE_NAME_PREFIX.length() + EVENT_COUNTER_WIDTH;
  private static final String PRIORITY_EVENT_SUFFIX = "_";
  private static final String NORMAL_EVENT_SUFFIX = "";

  private static final CrashlyticsReportJsonTransform TRANSFORM =
      new CrashlyticsReportJsonTransform();

  private static final Comparator<? super File> LATEST_SESSION_ID_FIRST_COMPARATOR =
      (f1, f2) -> f2.getName().compareTo(f1.getName());

  private static final FilenameFilter EVENT_FILE_FILTER =
      (f, name) -> name.startsWith(EVENT_FILE_NAME_PREFIX);

  private final AtomicInteger eventCounter = new AtomicInteger(0);

  private final FileStore fileStore;

  @NonNull private final SettingsProvider settingsProvider;

  public CrashlyticsReportPersistence(FileStore fileStore, SettingsProvider settingsProvider) {
    this.fileStore = fileStore;
    this.settingsProvider = settingsProvider;
  }

  public void persistReport(@NonNull CrashlyticsReport report) {
    final Session session = report.getSession();
    if (session == null) {
      Logger.getLogger().d("Could not get session for report");
      return;
    }

    final String sessionId = session.getIdentifier();
    try {
      final String json = TRANSFORM.reportToJson(report);
      writeTextFile(fileStore.getSessionFile(sessionId, REPORT_FILE_NAME), json);
      writeTextFile(
          fileStore.getSessionFile(sessionId, SESSION_START_TIMESTAMP_FILE_NAME),
          "",
          session.getStartedAt());
    } catch (IOException e) {
      Logger.getLogger().d("Could not persist report for session " + sessionId, e);
    }
  }

  /**
   * Persist an event for a given session with normal priority.
   *
   *
Only a certain number of normal priority events are stored per-session. When this maximum is
   * reached, the oldest events will be dropped.
   */
  public void persistEvent(
      @NonNull CrashlyticsReport.Session.Event event, @NonNull String sessionId) {
    persistEvent(event, sessionId, false);
  }

  /**
   * Persist an event for a given session, specifying whether or not it is high priority.
   *
   *
Only a certain number of normal priority events are stored per-session. When this maximum is
   * reached, the oldest events will be dropped. High priority events are not subject to this limit.
   */
  public void persistEvent(
      @NonNull CrashlyticsReport.Session.Event event,
      @NonNull String sessionId,
      boolean isHighPriority) {
    int maxEventsToKeep = settingsProvider.getSettingsSync().sessionData.maxCustomExceptionEvents;
    final String json = TRANSFORM.eventToJson(event);
    final String fileName = generateEventFilename(eventCounter.getAndIncrement(), isHighPriority);
    try {
      writeTextFile(fileStore.getSessionFile(sessionId, fileName), json);
    } catch (IOException e) {
      Logger.getLogger().w("Could not persist event for session " + sessionId, e);
    }
    trimEvents(sessionId, maxEventsToKeep);
  }

  /**
   * @return all open session ids, sorted in ascending order of recency (such that the first element
   *     is the most recently-opened session ID).
   */
  public SortedSet<String> getOpenSessionIds() {
    return new TreeSet<>(fileStore.getAllOpenSessionIds()).descendingSet();
  }

  /**
   * Gets the startTimestampMs of the given sessionId.
   *
   * @return startTimestampMs
   */
  public long getStartTimestampMillis(String sessionId) {
    final File sessionStartTimestampFile =
        fileStore.getSessionFile(sessionId, SESSION_START_TIMESTAMP_FILE_NAME);
    return sessionStartTimestampFile.lastModified();
  }

  public boolean hasFinalizedReports() {
    return !fileStore.getReports().isEmpty()
        || !fileStore.getPriorityReports().isEmpty()
        || !fileStore.getNativeReports().isEmpty();
  }

  public void deleteAllReports() {
    deleteFiles(fileStore.getReports());
    deleteFiles(fileStore.getPriorityReports());
    deleteFiles(fileStore.getNativeReports());
  }

  private void deleteFiles(List<File> files) {
    for (File file : files) {
      //noinspection ResultOfMethodCallIgnored
      file.delete();
    }
  }

  /**
   * Finalizes all open sessions except for the current session ID
   *
   * @param currentSessionId current session ID (to skip). If this is null, all open sessions will
   *     be finalized.
   */
  public void finalizeReports(@Nullable String currentSessionId, long sessionEndTime) {
    Collection<String> sessions = capAndGetOpenSessions(currentSessionId);
    for (String sessionId : sessions) {
      Logger.getLogger().v("Finalizing report for session " + sessionId);
      synthesizeReport(sessionId, sessionEndTime);
      // TODO: log deleted or failed
      fileStore.deleteSessionFiles(sessionId);
    }
    capFinalizedReports();
  }

  public void finalizeSessionWithNativeEvent(
      String previousSessionId, CrashlyticsReport.FilesPayload ndkPayload) {
    final File reportFile = fileStore.getSessionFile(previousSessionId, REPORT_FILE_NAME);
    Logger.getLogger()
        .d("Writing native session report for " + previousSessionId + " to file: " + reportFile);
    synthesizeNativeReportFile(reportFile, ndkPayload, previousSessionId);
  }

  /**
   * @return finalized (no longer changing) Crashlytics Reports, sorted first from high to low
   *     priority, secondarily sorted from most recent to least
   */
  @NonNull
  public List<CrashlyticsReportWithSessionId> loadFinalizedReports() {
    final List<File> allReportFiles = getAllFinalizedReportFiles();
    final ArrayList<CrashlyticsReportWithSessionId> allReports = new ArrayList<>();
    for (File reportFile : allReportFiles) {
      try {
        CrashlyticsReport jsonReport = TRANSFORM.reportFromJson(readTextFile(reportFile));
        allReports.add(
            CrashlyticsReportWithSessionId.create(jsonReport, reportFile.getName(), reportFile));
      } catch (IOException e) {
        Logger.getLogger().w("Could not load report file " + reportFile + "; deleting", e);
        reportFile.delete();
      }
    }
    return allReports;
  }

  private SortedSet<String> capAndGetOpenSessions(@Nullable String currentSessionId) {
    fileStore.cleanupPreviousFileSystems();

    SortedSet<String> openSessionIds = getOpenSessionIds();
    if (currentSessionId != null) {
      openSessionIds.remove(currentSessionId);
    }
    if (openSessionIds.size() <= MAX_OPEN_SESSIONS) {
      return openSessionIds;
    }

    while (openSessionIds.size() > MAX_OPEN_SESSIONS) {
      String id = openSessionIds.last();
      Logger.getLogger().d("Removing session over cap: " + id);
      // TODO: log deleted or failed
      fileStore.deleteSessionFiles(id);
      openSessionIds.remove(id);
    }
    return openSessionIds;
  }

  private void capFinalizedReports() {
    int maxReportsToKeep = settingsProvider.getSettingsSync().sessionData.maxCompleteSessionsCount;
    List<File> finalizedReportFiles = getAllFinalizedReportFiles();

    int fileCount = finalizedReportFiles.size();
    if (fileCount <= maxReportsToKeep) {
      return;
    }

    // Make a sublist of the reports that go over the size limit
    List<File> filesToRemove = finalizedReportFiles.subList(maxReportsToKeep, fileCount);
    for (File reportFile : filesToRemove) {
      reportFile.delete();
    }
  }

  /**
   * @return finalized (no longer changing) files for Crashlytics Reports, sorted first from high to
   *     low priority, secondarily sorted from most recent to least
   */
  private List<File> getAllFinalizedReportFiles() {
    List<File> sortedPriorityReports = new ArrayList<>();
    sortedPriorityReports.addAll(fileStore.getPriorityReports());
    sortedPriorityReports.addAll(fileStore.getNativeReports());
    Collections.sort(sortedPriorityReports, LATEST_SESSION_ID_FIRST_COMPARATOR);

    List<File> sortedReports = fileStore.getReports();
    Collections.sort(sortedReports, LATEST_SESSION_ID_FIRST_COMPARATOR);

    sortedPriorityReports.addAll(sortedReports);

    return sortedPriorityReports;
  }

  private void synthesizeReport(String sessionId, long sessionEndTime) {
    List<File> eventFiles = fileStore.getSessionFiles(sessionId, EVENT_FILE_FILTER);

    // Only process the session if it has associated events
    if (eventFiles.isEmpty()) {
      Logger.getLogger().v("Session " + sessionId + " has no events.");
      return;
    }

    Collections.sort(eventFiles);

    final List<Event> events = new ArrayList<>();
    boolean isHighPriorityReport = false;

    for (File eventFile : eventFiles) {
      try {
        Event event = TRANSFORM.eventFromJson(readTextFile(eventFile));
        events.add(event);
        isHighPriorityReport = isHighPriorityReport || isHighPriorityEventFile(eventFile.getName());
      } catch (IOException e) {
        Logger.getLogger().w("Could not add event to report for " + eventFile, e);
      }
    }

    // b/168902195
    if (events.isEmpty()) {
      Logger.getLogger().w("Could not parse event files for session " + sessionId);
      return;
    }

    String userId = UserMetadata.readUserId(sessionId, fileStore);

    final File reportFile = fileStore.getSessionFile(sessionId, REPORT_FILE_NAME);
    synthesizeReportFile(reportFile, events, sessionEndTime, isHighPriorityReport, userId);
  }

  private void synthesizeNativeReportFile(
      @NonNull File reportFile,
      @NonNull CrashlyticsReport.FilesPayload ndkPayload,
      @NonNull String previousSessionId) {
    try {
      final CrashlyticsReport report =
          TRANSFORM.reportFromJson(readTextFile(reportFile)).withNdkPayload(ndkPayload);

      writeTextFile(fileStore.getNativeReport(previousSessionId), TRANSFORM.reportToJson(report));
    } catch (IOException e) {
      Logger.getLogger().w("Could not synthesize final native report file for " + reportFile, e);
    }
  }

  private void synthesizeReportFile(
      @NonNull File reportFile,
      @NonNull List<Event> events,
      long sessionEndTime,
      boolean isHighPriorityReport,
      @Nullable String userId) {
    try {
      CrashlyticsReport report =
          TRANSFORM
              .reportFromJson(readTextFile(reportFile))
              .withSessionEndFields(sessionEndTime, isHighPriorityReport, userId)
              .withEvents(ImmutableList.from(events));
      final Session session = report.getSession();

      if (session == null) {
        // This shouldn't happen, but is a valid state for NDK-based reports
        return;
      }

      File finalizedReportFile =
          isHighPriorityReport
              ? fileStore.getPriorityReport(session.getIdentifier())
              : fileStore.getReport(session.getIdentifier());
      writeTextFile(finalizedReportFile, TRANSFORM.reportToJson(report));
    } catch (IOException e) {
      Logger.getLogger().w("Could not synthesize final report file for " + reportFile, e);
    }
  }

  private static boolean isHighPriorityEventFile(@NonNull String fileName) {
    return fileName.startsWith(EVENT_FILE_NAME_PREFIX) && fileName.endsWith(PRIORITY_EVENT_SUFFIX);
  }

  private static boolean isNormalPriorityEventFile(@NonNull File dir, @NonNull String name) {
    return name.startsWith(EVENT_FILE_NAME_PREFIX) && !name.endsWith(PRIORITY_EVENT_SUFFIX);
  }

  @NonNull
  private static String generateEventFilename(int eventNumber, boolean isHighPriority) {
    final String paddedEventNumber = String.format(Locale.US, EVENT_COUNTER_FORMAT, eventNumber);
    final String prioritySuffix = isHighPriority ? PRIORITY_EVENT_SUFFIX : NORMAL_EVENT_SUFFIX;
    return EVENT_FILE_NAME_PREFIX + paddedEventNumber + prioritySuffix;
  }

  private int trimEvents(String sessionId, int maximum) {
    final List<File> normalPriorityEventFiles =
        fileStore.getSessionFiles(
            sessionId, CrashlyticsReportPersistence::isNormalPriorityEventFile);
    Collections.sort(normalPriorityEventFiles, CrashlyticsReportPersistence::oldestEventFileFirst);
    return capFilesCount(normalPriorityEventFiles, maximum);
  }

  @NonNull
  private static String getEventNameWithoutPriority(@NonNull String eventFileName) {
    return eventFileName.substring(0, EVENT_NAME_LENGTH);
  }

  private static int oldestEventFileFirst(@NonNull File f1, @NonNull File f2) {
    final String name1 = getEventNameWithoutPriority(f1.getName());
    final String name2 = getEventNameWithoutPriority(f2.getName());
    return name1.compareTo(name2);
  }

  private static void writeTextFile(File file, String text) throws IOException {
    try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), UTF_8)) {
      writer.write(text);
    }
  }

  private static void writeTextFile(File file, String text, long lastModifiedTimestampSeconds)
      throws IOException {
    try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), UTF_8)) {
      writer.write(text);
      file.setLastModified(convertTimestampFromSecondsToMs(lastModifiedTimestampSeconds));
    }
  }

  @NonNull
  private static String readTextFile(@NonNull File file) throws IOException {
    final byte[] readBuffer = new byte[8192];
    final ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try (FileInputStream fileInput = new FileInputStream(file)) {
      int read;
      while ((read = fileInput.read(readBuffer)) > 0) {
        bos.write(readBuffer, 0, read);
      }
      return new String(bos.toByteArray(), UTF_8);
    }
  }

  /**
   * Deletes files from the list until the list size is equal to the maximum. If list is already
   * correctly sized, no files are deleted. List should be sorted in the order in which files should
   * be deleted.
   *
   * @return the number of files retained on disk
   */
  private static int capFilesCount(List<File> files, int maximum) {
    int numRetained = files.size();
    for (File f : files) {
      if (numRetained <= maximum) {
        return numRetained;
      }
      FileStore.recursiveDelete(f);
      numRetained--;
    }
    return numRetained;
  }

  private static long convertTimestampFromSecondsToMs(long timestampSeconds) {
    return timestampSeconds * 1000;
  }
}

redpajama_set_name: RedPajamaGithub


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="wrap_content"
    android:orientation="vertical"
    android:paddingTop="13dp" >

    <TextView
        android:id="@+id/tv_time"
        style="@style/chat_text_date_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_chat_top" >

        <com.zjk.wifiproject.view.CircularImageView
            android:id="@+id/iv_avatar"
            android:layout_width="@dimen/base_scrollview_top_height"
            android:layout_height="@dimen/base_scrollview_top_height"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="@dimen/margin_chat_top"
            android:background="@drawable/sanpang_1"
            android:scaleType="fitXY" />

        <LinearLayout
            android:id="@+id/layout_voice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/margin_chat_top"
            android:layout_marginTop="10dp"
            android:layout_toRightOf="@id/iv_avatar"
            android:gravity="left"
            android:background="@drawable/chat_left_qp"
            android:minWidth="80dp"
            android:minHeight="45dp"
            android:paddingBottom="5dp"
            android:paddingLeft="15dp"
            android:paddingRight="5dp"
            android:paddingTop="5dp" >

            <ImageView
                android:id="@+id/iv_voice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/voice_right3" />
        </LinearLayout>

        <TextView
            android:id="@+id/tv_voice_length"
            style="@style/chat_text_name_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@id/layout_voice"
            android:gravity="center" />

    </RelativeLayout>

</LinearLayout>


text:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2015.11.10 at 10:56:43 AM CET
//

package com.github.sandor_balazs.sentiment_analysis.jaxb.corpus;

import javax.xml.bind.annotation.XmlRegistry;

/**
 * This object contains factory methods for each
 * Java content interface and Java element interface
 * generated in the com.github.sandor_balazs.sentiment_analysis.jaxb.corpus package.
 *
An ObjectFactory allows you to programatically
 * construct new instances of the Java representation
 * for XML content. The Java representation of XML
 * content can consist of schema derived interfaces
 * and classes representing the binding of schema
 * type definitions, element declarations and model
 * groups.  Factory methods for each of these are
 * provided in this class.
 *
 */
@XmlRegistry
public class ObjectFactory {

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.github.sandor_balazs.sentiment_analysis.jaxb.corpus
     *
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link ReviewCorpus }
     *
     */
    public ReviewCorpus createReviewCorpus() {
        return new ReviewCorpus();
    }

    /**
     * Create an instance of {@link OpinionContainer }
     *
     */
    public OpinionContainer createOpinionContainer() {
        return new OpinionContainer();
    }

    /**
     * Create an instance of {@link Opinion }
     *
     */
    public Opinion createOpinion() {
        return new Opinion();
    }

    /**
     * Create an instance of {@link SentenceContainer }
     *
     */
    public SentenceContainer createSentenceContainer() {
        return new SentenceContainer();
    }

    /**
     * Create an instance of {@link Review }
     *
     */
    public Review createReview() {
        return new Review();
    }

    /**
     * Create an instance of {@link Sentence }
     *
     */
    public Sentence createSentence() {
        return new Sentence();
    }

}


text:
import Ember from "ember";
import DS from "ember-data";

export default DS.Model.extend({
  title: DS.attr('string'),
  isParent: DS.attr('boolean', { defaultValue: false }),
  isSection: DS.attr('boolean', { defaultValue: false }),
  parentChecklistItem: DS.attr('string'),

  isChild: Ember.computed('parentChecklistItem', function() {
    return !!this.get('parentChecklistItem');
  }),

  // data attributes
  draggable: true,
  inserting: false,
  sectionIsCollapsed: false,
  isCollapsedSectionChild: false
});


text:
import React from 'react';
import { connect } from 'react-redux';

import { push, replace, goBack } from 'react-router-redux';

export default function (Component) {
  class WithRouter extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
    render() {
      return (
        <Component
          {...this.props}
        />
      );
    }
  }

  function mapDispatchToProps(dispatch) {
    return {
      changeRoute: (route) => dispatch(push(route)),
      replaceRoute: (route) => dispatch(replace(route)),
      goBackRoute: () => dispatch(goBack()),
    };
  }

  return connect(null, mapDispatchToProps)(WithRouter);
}


text:
export default class Hex {
    constructor(public q: number,
                public r: number,
                public s: number) {
    }
}


text:
package no.ssb.jsonstat.v2;

/**
 * Thrown when trying to add a dimension twice.
 */
public class DuplicateDimensionException extends RuntimeException {

    /**
     * Constructs a new runtime exception with the specified detail message.
     * The cause is not initialized, and may subsequently be initialized by a
     * call to {@link #initCause}.
     *
     * @param message the detail message. The detail message is saved for
     *                later retrieval by the {@link #getMessage()} method.
     */
    public DuplicateDimensionException(String message) {
        super(message);
    }
}


text:
Rails.application.routes.draw do
  mount Ckeditor::Engine => '/ckeditor'
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'

  get 'cities/find/location', to: 'cities#by_location', as: 'city_by_location'
  get 'cities/search', to: 'cities#search', as: 'search_cities'
  get 'cities/:id/search', to: 'cities#search_items', as: 'search_items'

  get 'articles/search', to: 'articles#search', as: 'search_articles'

  resources :articles
  resources :cities, except: [:new, :create]
  resources :items, only: [:create, :update, :destroy]
  resources :bins, only: [:create, :update, :destroy]

  devise_for :admins
  devise_for :city_officials

  # The root url points to a stub page. The only role of this page is to see if a user has location
  # enabled and, if so, direct them to their cities page. Otherwise, they are sent to the real home
  # page, which is cities#index.
  root to: 'root#redirect'
end


text:
import arrayEvery from './_arrayEvery';
import createOver from './_createOver';

/**
 * Creates a function that checks if **all** of the `predicates` return
 * truthy when invoked with the arguments it receives.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Util
 * @param {...(Function|Function[])} predicates The predicates to check.
 * @returns {Function} Returns the new function.
 * @example
 *
 * var func = _.overEvery(Boolean, isFinite);
 *
 * func('1');
 * // => true
 *
 * func(null);
 * // => false
 *
 * func(NaN);
 * // => false
 */
var overEvery = createOver(arrayEvery);

export default overEvery;


text:
var fs = require('fs');
var path = require('path');

//** 启动log4js配置
var log4js = require('log4js');
log4js.configure(path.join(__dirname,'../config/log4js.json'), {cwd: path.join(__dirname, '..')});
var logger = log4js.getLogger(path.relative(process.cwd(),__filename));

//** CronJob package
var CronJob = require('cron').CronJob;

var mongoose = require('mongoose');
var config = {
	mail: require('../config/mail'),
	db: require('../config/db')
};

//import the models
var models = {};
fs.readdirSync(path.join(__dirname, '../models')).forEach(function(file) {
	if (/\.js$/.test(file)) {
		var modelName = file.substr(0, file.length - 3);
		models[modelName] = require('../models/' + modelName)(mongoose);
	}
});

mongoose.connect(config.db.URI, function onMongooseError(err) {
	if (err) {
		logger.error('Error: can not open Mongodb.');
		throw err;
	}
});

//** 股票服务
var processStockJob = new CronJob({
	//** 每5秒钟询价一次
	cronTime: '*/5 * * * * *',
	onTick: function() {
		logger.info('发送指令: 股票投资组合询价');
		models.TradePortfolio.processStock(function(err){
			if (err) return logger.error(err);
			logger.info('成功处理指令: 股票投资组合询价');
		});
	},
	start: true,
	runOnInit: true, //** execute right now!
});
logger.info('CITIC 股票投资组合服务已开启。');

process.on('SIGTERM', function() {
	logger.info('StockService 因 kill 退出。');
	process.exit(1);
});

//** process uncaughtException
process.on('uncaughtException', function(e){
	logger.warn('StockService 因 uncaughtException 退出。');
	logger.debug(e);
	process.exit(1);
});


text:
/************************************************************************************
 * include/tinyara/input/touchscreen.h
 *
 *   Copyright (C) 2011-2012, 2017 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ************************************************************************************/

/* The TOUCHSCREEN driver exports a standard character driver interface. By
 * convention, the touchscreen driver is registers as an input device at
 * /dev/inputN where N uniquely identifies the driver instance.
 *
 * This header file documents the generic interface that all tinyara
 * touchscreen devices must conform.  It adds standards and conventions on
 * top of the standard character driver interface.
 */

#ifndef __INCLUDE_TINYARA_INPUT_TOUCHSCREEN_H
#define __INCLUDE_TINYARA_INPUT_TOUCHSCREEN_H

/************************************************************************************
 * Included Files
 ************************************************************************************/

#include <tinyara/config.h>
#include <tinyara/fs/ioctl.h>

#ifdef CONFIG_INPUT

/************************************************************************************
 * Pre-processor Definitions
 ************************************************************************************/

/* IOCTL Commands *******************************************************************/
/* Common TSC IOCTL commands */

#define TSIOC_SETCALIB       _TSIOC(0x0001)  /* arg: Pointer to int calibration value */
#define TSIOC_GETCALIB       _TSIOC(0x0002)  /* arg: Pointer to int calibration value */
#define TSIOC_SETFREQUENCY   _TSIOC(0x0003)  /* arg: Pointer to uint32_t frequency value */
#define TSIOC_GETFREQUENCY   _TSIOC(0x0004)  /* arg: Pointer to uint32_t frequency value */

#define TSC_FIRST            0x0001          /* First common command */
#define TSC_NCMDS            4               /* Four common commands */

/* User defined ioctl commands are also supported.  However, the TSC driver must
 * reserve a block of commands as follows in order prevent IOCTL command numbers
 * from overlapping.
 *
 * This is generally done as follows.  The first reservation for TSC driver A would
 * look like:
 *
 *   TSC_A_FIRST                 (TSC_FIRST + TSC_NCMDS)     <- First command
 *   TSC_A_NCMDS                 42                          <- Number of commands
 *
 * IOCTL commands for TSC driver A would then be defined in a TSC A header file like:
 *
 *   TSCIOC_A_CMD1               _TSIOC(TSC_A_FIRST+0)
 *   TSCIOC_A_CMD2               _TSIOC(TSC_A_FIRST+1)
 *   TSCIOC_A_CMD3               _TSIOC(TSC_A_FIRST+2)
 *   ...
 *   TSCIOC_A_CMD42              _TSIOC(TSC_A_FIRST+41)
 *
 * The next reservation would look like:
 *
 *   TSC_B_FIRST                 (TSC_A_FIRST + TSC_A_NCMDS) <- Next command
 *   TSC_B_NCMDS                 77                          <- Number of commands
 */

/* These definitions provide the meaning of all of the bits that may be
 * reported in the struct touch_point_s flags.
 */

#define TOUCH_DOWN           (1 << 0) /* A new touch contact is established */
#define TOUCH_MOVE           (1 << 1) /* Movement occurred with previously reported contact */
#define TOUCH_UP             (1 << 2) /* The touch contact was lost */
#define TOUCH_ID_VALID       (1 << 3) /* Touch ID is certain */
#define TOUCH_POS_VALID      (1 << 4) /* Hardware provided a valid X/Y position */
#define TOUCH_PRESSURE_VALID (1 << 5) /* Hardware provided a valid pressure */
#define TOUCH_SIZE_VALID     (1 << 6) /* Hardware provided a valid H/W contact size */

/************************************************************************************
 * Public Types
 ************************************************************************************/

/* This structure contains information about a single touch point.
 * Positional units are device specific.
 */

struct touch_point_s {
	uint8_t  id;       /* Unique identifies contact; Same in all reports for the contact */
	uint8_t  flags;    /* See TOUCH_* definitions above */
	int16_t  x;        /* X coordinate of the touch point (uncalibrated) */
	int16_t  y;        /* Y coordinate of the touch point (uncalibrated) */
	int16_t  h;        /* Height of touch point (uncalibrated) */
	int16_t  w;        /* Width of touch point (uncalibrated) */
	uint16_t pressure; /* Touch pressure */
};

/* The typical touchscreen driver is a read-only, input character device driver.
 * the driver write() method is not supported and any attempt to open the
 * driver in any mode other than read-only will fail.
 *
 * Data read from the touchscreen device consists only of touch events and
 * touch sample data.  This is reflected by struct touch_sample_s.  This
 * structure is returned by either the driver read method.
 *
 * On some devices, multiple touchpoints may be supported. So this top level
 * data structure is a struct touch_sample_s that "contains" a set of touch
 * points.  Each touch point is managed individually using an ID that identifies
 * a touch from first contact until the end of the contact.
 */

struct touch_sample_s {
	int npoints;                   /* The number of touch points in point[] */
	struct touch_point_s point[1]; /* Actual dimension is npoints */
};
#define SIZEOF_TOUCH_SAMPLE_S(n) (sizeof(struct touch_sample_s) + ((n) - 1) * sizeof(struct touch_point_s))

/************************************************************************************
 * Public Function Prototypes
 ************************************************************************************/

#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
#else
#define EXTERN extern
#endif

#undef EXTERN
#ifdef __cplusplus
}
#endif

#endif /* CONFIG_INPUT */
#endif /* __INCLUDE_TINYARA_INPUT_TOUCHSCREEN_H */


text:
class TransactionController < ApplicationController
	def index
		puts "*"*50
		puts params
		# transactions should return two arrays, first being earnings and second charges
		# A request without the userId will return all transactions
		@transactions = [[], []]

		user_id = params[:user_id].to_i if params[:user_id]

		if user_id
			@transactions[0] = Transaction.where(user_id: user_id, transaction_type: 'earning').order('created_at ASC')
			@transactions[1] = Transaction.where(user_id: user_id, transaction_type: 'charge').order('created_at ASC')
		else
			@transactions[0] = Transaction.where(transaction_type: 'earning').order('created_at ASC')
			@transactions[1] = Transaction.where(transaction_type: 'charge').order('created_at ASC')
		end
		render :json => @transactions
	end

end


text:
namespace EntityFrameworkPerformanceTests.CodeFirst
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    [Table("Purchasing.vVendorWithAddresses")]
    public partial class vVendorWithAddress
    {
        [Key]
        [Column(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int BusinessEntityID { get; set; }

        [Key]
        [Column(Order = 1)]
        [StringLength(50)]
        public string Name { get; set; }

        [Key]
        [Column(Order = 2)]
        [StringLength(50)]
        public string AddressType { get; set; }

        [Key]
        [Column(Order = 3)]
        [StringLength(60)]
        public string AddressLine1 { get; set; }

        [StringLength(60)]
        public string AddressLine2 { get; set; }

        [Key]
        [Column(Order = 4)]
        [StringLength(30)]
        public string City { get; set; }

        [Key]
        [Column(Order = 5)]
        [StringLength(50)]
        public string StateProvinceName { get; set; }

        [Key]
        [Column(Order = 6)]
        [StringLength(15)]
        public string PostalCode { get; set; }

        [Key]
        [Column(Order = 7)]
        [StringLength(50)]
        public string CountryRegionName { get; set; }
    }
}


text:
require 'open-uri'

module Spree
  module Wombat
    module Handler
      class UpdateProductHandler < ProductHandlerBase

        def process
          id = params.delete(:id)
          product = Spree::Variant.where(is_master: true, sku: params[:sku]).first.product
          return response("Cannot find product with SKU #{params[:sku]}!", 500) unless product

          # Disable the after_touch callback on taxons
          Spree::Product.skip_callback(:touch, :after, :touch_taxons)

          Spree::Product.transaction do
            @product = process_root_product(product, root_product_attrs)
            process_images(@product.master, @master_images)
            process_child_products(@product, children_params) if @children_params
          end

          if @product.valid?
            # set it again, and touch the product
            Spree::Product.set_callback(:touch, :after, :touch_taxons)
            @product.touch

            if @product.variants.count > 0
              response "Product #{@product.sku} updated, with child skus: #{@product.variants.pluck(:sku)}"
            else
              response "Product #{@product.sku} updated"
            end
          else
            response "Cannot update the product due to validation errors", 500
          end

        end

        # the Spree::Product and Spree::Variant master
        # it's the top level 'product'
        def process_root_product(product, params)
          product.update_attributes(params)
          process_option_types(product, @root_options)
          process_properties(product, @properties)

          product
        end

      end
    end
  end
end


text:
require 'rexml/parsers/sax2parser'
require 'rexml/sax2listener'

module ETL #:nodoc:
  module Parser #:nodoc:
    # ETL parser implementation which uses SAX to parse XML files.
    class SaxParser < ETL::Parser::Parser

      # The write trigger causes whatever values are currently specified for the row to be returned.
      # After returning the values will not be cleared, thus allowing for values which are assigned
      # higher in the XML tree to remain in memory.
      attr_accessor :write_trigger

      # Initialize the parser
      # * <tt>source</tt>: The Source object
      # * <tt>options</tt>: Parser options Hash
      def initialize(source, options={})
        super
        configure
      end

      # Returns each row
      def each(&block)
        Dir.glob(file).each do |file|
          parser = REXML::Parsers::SAX2Parser.new(File.new(file))
          listener = Listener.new(self, &block)
          parser.listen(listener)
          parser.parse
        end
      end

      # Get an array of Field objects
      def fields
        @fields ||= []
      end

      private
      def configure
        #puts "write trigger in source.definition: #{source.definition[:write_trigger]}"
        self.write_trigger = source.definition[:write_trigger]
        # map paths to field names
        source.definition[:fields].each do |name, path|
          #puts "defined field #{name}, path: #{path}"
          fields << Field.new(name, XPath::Path.parse(path))
        end
      end

      # Class representing a field to be loaded from the source
      class Field
        # The name of the field
        attr_reader :name
        # The XPath-like path to the field in the XML document
        attr_reader :path

        def initialize(name, path) #:nodoc
          @name = name
          @path = path
        end
      end
    end

    class Listener #:nodoc:
      include REXML::SAX2Listener
      def initialize(parser, &block)
        @parser = parser
        @row = {}
        @value = nil
        @proc = Proc.new(&block)
      end
      def cdata(text)
        characters(text)
      end
      def characters(text)
        text = text.strip
        if (!text.nil? && text != '')
          @value ||= ''
          @value << text
        end
      end
      def start_document
        @path = XPath::Path.new
      end
      def end_document

      end
      def start_element(uri, localname, qname, attributes)
        element = XPath::Element.new(localname, attributes)
        @path.elements << element

        @parser.fields.each do |field|
          #puts "#{@path} match? #{field.path}"
          if @path.match?(field.path)
            #puts "field.path: #{field.path}"
            if field.path.is_attribute?
              #puts "setting @row[#{field.name}] to #{element.attributes[field.path.attribute]}"
              @row[field.name] = element.attributes[field.path.attribute]
            end
          end
        end
      end
      def end_element(uri, localname, qname)
        element = @path.elements.last

        @parser.fields.each do |field|
          #puts "#{@path} match? #{field.path}"
          if @path.match?(field.path)
            #puts "field.path: #{field.path}"
            if !field.path.is_attribute?
              @row[field.name] = @value
            end
          end
        end

        #puts @path.to_s
        if @path.match?(@parser.write_trigger)
          #puts "matched: #{@path} =~ #{@parser.write_trigger}"
          #puts "calling proc with #{@row.inspect}"
          @proc.call(@row.clone)
        end

        @value = nil
        @path.elements.pop
      end
      def progress(position)
        @position = position
      end
    end

    # Module which contains classes that are used for XPath-like filtering
    # on the SAX parser
    module XPath #:nodoc:
      class Path #:nodoc:
        # Get the elements in the path
        attr_accessor :elements

        # Initialize
        def initialize
          @elements = []
        end

        # Convert to a string representation
        def to_s
          @elements.map{ |e| e.to_s }.join("/")
        end

        # Returns true if the last part of the path refers to an attribute
        def is_attribute?
          elements.last.attributes.length > 0
        end

        # Return the name of the attribute referenced by the last element in this path. Returns nil if the last element
        # does not reference an attribute.
        #
        # Warning: the path must only reference a single attribute, otherwise the result of this method will be random,
        # since attributes are stored in a Hash.
        def attribute
          return nil unless is_attribute?
          elements.last.attributes.keys.first
        end

        # Return true if this XPath::Path matches the given path string. This is a fail-fast match, so the first mismatch
        # will cause the method to return false.
        def match?(s)
          path = Path.parse(s)
          return false unless path.elements.length == elements.length
          elements.each_with_index do |element, index|
            path_element = path.elements[index]
            return false if path_element.nil?
            return false if element.name != path_element.name
            path_element.attributes.each do |key, value|
              return false unless element.attributes[key] =~ value
            end
          end
          return true
        end

        # Parse the string into an XPath::Path object
        def self.parse(s)
          return s if s.is_a?(Path)
          path = Path.new
          parts = s.split('/')
          parts.each_with_index do |part, i|
            attributes = {}
            part.gsub!(/(.*)\[(.*)\]/, '\1')
            if !$2.nil?
              $2.split(",").each do |pair|
                key, value = pair.split("=")
                value = ".*" if value.nil?
                attributes[key] = Regexp.new(value)
              end
            end
            path.elements << Element.new(part, attributes)
          end
          path
        end
      end
      class Element #:nodoc
        attr_reader :name
        attr_reader :attributes
        def initialize(name, attributes={})
          @name = name
          @attributes = attributes
        end
        def to_s
          s = "#{name}"
          if !@attributes.empty?
            attr_str = @attributes.collect do |key,value|
              value = value.source if value.is_a?(Regexp)
              "#{key}=#{value}"
            end.join(",")
            s << "[" + attr_str + "]"
          end
          s
        end
      end
    end
  end
end


text:
$LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require 'xbmc-activerecord'
require 'spec'
require 'spec/autorun'

Spec::Runner.configure do |config|

end


text:
package 华为武汉长沙地区实习招聘;

import java.util.Scanner;

public class Excel的列编号 {
	private static Scanner sc;
	public static void main(String[] args) {
		sc=new Scanner(System.in);
		System.out.println(calculate(sc.nextLine()));

	}
private static String calculate(String str) {
	int result=0;
	for(int i=0;i<str.length();i++){
		char c=str.charAt(i);
		result=(int) (result+(int)(c-96)*Math.pow(26, str.length()-1-i));
	}
	return String.valueOf(result);
}
}