package com.nightonke.githubwidget; import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.media.ThumbnailUtils; import android.os.Build; import android.preference.PreferenceManager; import android.support.v4.content.ContextCompat; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.View; import android.view.WindowManager; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.widget.RemoteViews; import com.github.johnpersano.supertoasts.SuperToast; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Locale; import java.util.TimeZone; import java.util.regex.PatternSyntaxException; /** * Created by Weiping on 2016/4/25. */ public class Util { public static final int HALF_AN_HOUR = 30 * 60 * 1000; public static final float WIDGET_2_NUMBER_HEIGHT = 50f; public static final float WIDGET_2_LETTER_HEIGHT = 25f; public static final float WIDGET_2_LETTER_PADDING_BOTTOM = 20f; public static final String TAG = "GithubWidget"; public static final String LIST_VIEW_CONTENTS_URL_PREFIX = "https://github.com/"; public static int getScreenWidth(Context context) { Display localDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); Point point = new Point(); localDisplay.getSize(point); return point.x; } public static int getScreenHeight(Context context) { Display localDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); Point point = new Point(); localDisplay.getSize(point); return point.y; } public final static String WIDTH_STRING = "<svg width=\""; public final static int BLOCK_WIDTH = 13; public static int getContributionsColumnNumber(String string) { int width = Integer.valueOf( string.substring( string.indexOf(WIDTH_STRING) + WIDTH_STRING.length(), string.indexOf("\"", WIDTH_STRING.length() + 1))); return width / BLOCK_WIDTH; } public final static String FILL_STRING = "fill=\""; public final static String DATA_STRING = "data-count=\""; public final static String DATE_STRING = "data-date=\""; public static ArrayList<Day> getContributionsFromString(String string) { ArrayList<Day> contributions = new ArrayList<>(); int fillPos = -1; int dataPos = -1; int datePos = -1; while (true) { fillPos = string.indexOf(FILL_STRING, fillPos + 1); dataPos = string.indexOf(DATA_STRING, dataPos + 1); datePos = string.indexOf(DATE_STRING, datePos + 1); if (fillPos == -1) break; int level = 0; String levelString = string.substring(fillPos + FILL_STRING.length(), fillPos + FILL_STRING.length() + 7); switch (levelString) { case "#eeeeee": level = 0; break; case "#d6e685": level = 1; break; case "#8cc665": level = 2; break; case "#44a340": level = 3; break; case "#1e6823": level = 4; break; } int dataEndPos = string.indexOf("\"", dataPos + DATA_STRING.length()); String dataString = string.substring(dataPos + DATA_STRING.length(), dataEndPos); int data = Integer.valueOf(dataString); String dateString = string.substring(datePos + DATE_STRING.length(), datePos + DATE_STRING.length() + 11); contributions.add(new Day( Integer.valueOf(dateString.substring(0, 4)), Integer.valueOf(dateString.substring(5, 7)), Integer.valueOf(dateString.substring(8, 10)), level, data )); } return contributions; } /** * Get the day of week from a date. * 0 for SUN. * 1 for MON. * . * . * . * 6 for SAT. * * @param year The year of the date. * @param month The month of the date. * @param day The day of month of the date. * @return Integer to determine the day of week. */ public static int getWeekDayFromDate(int year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, day); calendar.add(Calendar.SECOND, 0); calendar.setFirstDayOfWeek(Calendar.SUNDAY); return calendar.get(Calendar.DAY_OF_WEEK) - 1; } /** * Get the short month name for a certain date. * * @param year The year of the date. * @param month The month of the date. * @param day The day of the date. * @return The short name of the month. */ public static String getShortMonthName(int year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, day); calendar.add(Calendar.SECOND, 0); SimpleDateFormat month_date = new SimpleDateFormat("MMM", Locale.US); return month_date.format(calendar.getTime()); } /** * Get the full month name for a certain date. * * @param year The year of the date. * @param month The month of the date. * @param day The day of the date. * @return The full name of the month. */ public static String getFullMonthName(int year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, day); calendar.add(Calendar.SECOND, 0); SimpleDateFormat month_date = new SimpleDateFormat("MMMM", Locale.US); return month_date.format(calendar.getTime()); } /** * Get the full month and day name for a certain date. * * @param year The year of the date. * @param month The month of the date. * @param day The day of the date. * @return The full name of the month and day. */ public static String getFullMonthDayName(int year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, day); calendar.add(Calendar.SECOND, 0); SimpleDateFormat month_date = new SimpleDateFormat("MMMM", Locale.US); return month_date.format(calendar.getTime()) + " " + day; } /** * Get the short year, month and day name for a certain date. * * @param year The year of the date. * @param month The month of the date. * @param day The day of the date. * @return The short name of the year, month and day. */ public static String getShortDateName(int year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, day); calendar.add(Calendar.SECOND, 0); SimpleDateFormat month_date = new SimpleDateFormat("MMM", Locale.US); return month_date.format(calendar.getTime()) + " " + day + ", " + year; } /** * Get the first letter of a weekday. * * @param weekDay Integer from 0 to 6 for weekday. * @return The first letter for the weekday. */ public static String getWeekdayFirstLetter(int weekDay) { switch (weekDay) { case 0: return "S"; case 1: return "M"; case 2: return "T"; case 3: return "W"; case 4: return "T"; case 5: return "F"; case 6: return "S"; default: return ""; } } /** * Dp to px. * * @param dp Value of dp. * @return Value of px. */ public static int dp2px(float dp){ DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); float px = dp * (metrics.densityDpi / 160f); return Math.round(px); } /** * Decode a resource to bitmap width sample size. * * @param resources Resources. * @param resId The id of the drawable. * @param reqWidth Width we need, in px. * @param reqHeight Height we need, in px. * @return The bitmap we loaded. */ public static Bitmap decodeSampledBitmapFromResource(Resources resources, int resId, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(resources, resId, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(resources, resId, options); } /** * Calculate the sample size. * * @param options Bitmap options. * @param reqWidth Width we need, in px. * @param reqHeight Height we need, in px. * @return Sample size. */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; } /** * Write the basic data of user. * * @param context Context. * @param string Data. */ @SuppressLint("CommitPrefEdits") public static void writeUserBasicData(Context context, String string) { SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit(); JSONObject jsonObject = null; try { jsonObject = new JSONObject(string); SettingsManager.setUserId(jsonObject.getInt("id")); } catch (JSONException e) { e.printStackTrace(); } editor.commit(); } /** * Get a 2D contributions bitmap. * * @param context Context. * @param data Data, from http get. * @param startWeekDay Start weekday. * @param baseColor Base color. * @param textColor Text color. * @param bitmapWidth Bitmap width. * @param bitmapHeight Bitmap height, this is useless. Because we calculate the height by width. * @param monthBelow Whether the months text is below the blocks. * @return The bitmap. */ public static Bitmap get2DBitmap( Context context, String data, Weekday startWeekDay, int baseColor, int textColor, int bitmapWidth, int bitmapHeight, boolean monthBelow) { Bitmap bitmap; Canvas canvas; Paint blockPaint; Paint monthTextPaint; Paint weekDayTextPaint; ArrayList<Day> contributions = Util.getContributionsFromString(data); int horizontalBlockNumber = Util.getContributionsColumnNumber(data); int verticalBlockNumber = 7; float ADJUST_VALUE = 0.8f; float blockWidth = bitmapWidth / (ADJUST_VALUE + horizontalBlockNumber) * (1.0F - 0.1F); float spaceWidth = bitmapWidth / (ADJUST_VALUE + horizontalBlockNumber) - blockWidth; float monthTextHeight = blockWidth * 1.5F; float weekTextHeight = blockWidth; float topMargin = monthBelow ? 15f : 7f; bitmapHeight = (int)(monthTextHeight + topMargin + verticalBlockNumber * (blockWidth + spaceWidth)); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG); blockPaint.setStyle(Paint.Style.FILL); monthTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); monthTextPaint.setTextSize(monthTextHeight); monthTextPaint.setColor(textColor); monthTextPaint.setTypeface( Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); weekDayTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); weekDayTextPaint.setTextSize(weekTextHeight); weekDayTextPaint.setColor(textColor); weekDayTextPaint.setTypeface( Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); // draw the text for weekdays float textStartHeight = (monthBelow ? 0 : monthTextHeight + topMargin) + blockWidth + spaceWidth; Paint.FontMetricsInt fontMetrics = monthTextPaint.getFontMetricsInt(); float baseline = ( textStartHeight + blockWidth + textStartHeight - fontMetrics.bottom - fontMetrics.top) / 2; canvas.drawText(Util.getWeekdayFirstLetter((startWeekDay.v + 1) % 7), 0, baseline, weekDayTextPaint); canvas.drawText(Util.getWeekdayFirstLetter((startWeekDay.v + 3) % 7), 0, baseline + 2 * (blockWidth + spaceWidth), weekDayTextPaint); canvas.drawText(Util.getWeekdayFirstLetter((startWeekDay.v + 5) % 7), 0, baseline + 4 * (blockWidth + spaceWidth), weekDayTextPaint); // draw the blocks int currentWeekDay = Util.getWeekDayFromDate( contributions.get(0).year, contributions.get(0).month, contributions.get(0).day); float x = weekTextHeight + topMargin; float y = (currentWeekDay - startWeekDay.v + 7) % 7 * (blockWidth + spaceWidth) + (monthBelow ? 0 : topMargin + monthTextHeight); int lastMonth = contributions.get(0).month - 1; for (Day day : contributions) { blockPaint.setColor(Util.calculateLevelColor(baseColor, day.level)); canvas.drawRect(x, y, x + blockWidth, y + blockWidth, blockPaint); currentWeekDay = (currentWeekDay + 1) % 7; if (currentWeekDay == startWeekDay.v) { // another column x += blockWidth + spaceWidth; y = monthBelow ? 0 : topMargin + monthTextHeight; if (!monthBelow && day.month != lastMonth) { // judge whether we should draw the text of month canvas.drawText( Util.getShortMonthName(day.year, day.month, day.day), x, monthTextHeight, monthTextPaint); lastMonth = day.month; } } else { y += blockWidth + spaceWidth; if (monthBelow && currentWeekDay == (startWeekDay.v + 6) % 7 && day.month != lastMonth) { // judge whether we should draw the text of month canvas.drawText( Util.getShortMonthName(day.year, day.month, day.day), x, y + monthTextHeight + topMargin, monthTextPaint); lastMonth = day.month; } } } return bitmap; } /** * Calculate the sum of contributions from xml. * * @param data The string of data. * @return The sum of contributions. */ public static int getContributionsSum(String data) { int sum = 0; int dataPos = -1; while (true) { dataPos = data.indexOf(DATA_STRING, dataPos + 1); if (dataPos == -1) break; int dataEndPos = data.indexOf("\"", dataPos + DATA_STRING.length()); String dataString = data.substring(dataPos + DATA_STRING.length(), dataEndPos); sum += Integer.valueOf(dataString); } return sum; } /** * Get round bitmap from normal bitmap. * * @param bitmap Normal bitmap. * @return Round bitmap. */ public static Bitmap getRoundBitmap(Bitmap bitmap) { int size = Math.min((bitmap.getWidth()), (bitmap.getHeight())); bitmap = ThumbnailUtils.extractThumbnail(bitmap, size, size); Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xffff0000; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); paint.setAntiAlias(true); paint.setDither(true); paint.setFilterBitmap(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawOval(rectF, paint); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth((float) 4); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } public static int lastToast = -1; /** * Show toast. * * @param text Resource id of the text. */ public static void showToast(int text) { if (!SettingsManager.getShowToast() || text == lastToast) return; lastToast = text; SuperToast.cancelAllSuperToasts(); SuperToast superToast = new SuperToast(GithubWidgetApplication.getAppContext()); superToast.setAnimations(SuperToast.Animations.FLYIN); superToast.setDuration(SuperToast.Duration.SHORT); superToast.setTextColor(Color.parseColor("#ffffff")); superToast.setTextSize(SuperToast.TextSize.SMALL); superToast.setText(GithubWidgetApplication.getAppContext().getResources().getString(text)); superToast.setBackground(SuperToast.Background.RED); superToast.setOnDismissListener(new SuperToast.OnDismissListener() { @Override public void onDismiss(View view) { lastToast = -1; } }); superToast.show(); } /** * Get the number of weekdays in the first week. * * @param contributions Days. * @param startWeekday Start from this weekday. * @return The number of weekdays in the first week. */ public static int getFirstWeekDaysNumber(ArrayList<Day> contributions, Weekday startWeekday) { int sum = 0; for (Day day : contributions) { sum++; if (getWeekDayFromDate(day.year, day.month, day.day) == startWeekday.v && sum != 0) break; } return sum; } /** * Get the number of weekdays in the last week. * * @param contributions Days. * @param startWeekday Start from this weekday. * @return The number of weekdays in the last week. */ public static int getLastWeekDaysNumber(ArrayList<Day> contributions, Weekday startWeekday) { int sum = 0; for (int i = contributions.size() - 1; i >= 0; i--) { Day day = contributions.get(i); sum++; if (getWeekDayFromDate(day.year, day.month, day.day) == startWeekday.v && sum != 0) break; } return sum; } /** * Calculate the red value for different level. * * @param baseR Red value of base color. * @param level Level. * @return The red value for the level of the base color. */ public static int calculateR(int baseR, int level) { switch (level) { case 0: return 238; case 1: return baseR; case 2: return (int) (baseR * (9 + 46 + 15) / (37f + 9 + 46 + 15)); case 3: return (int) (baseR * (46 + 15) / (37f + 9 + 46 + 15)); case 4: return (int) (baseR * (15) / (37f + 9 + 46 + 15)); default: return 238; } } /** * Calculate the green value for different level. * * @param baseG Green value of base color. * @param level Level. * @return The green value for the level of the base color. */ public static int calculateG(int baseG, int level) { switch (level) { case 0: return 238; case 1: return baseG; case 2: return (int) (baseG * (35 + 59 + 104) / (32f + 35 + 59 + 104)); case 3: return (int) (baseG * (59 + 104) / (32f + 35 + 59 + 104)); case 4: return (int) (baseG * (104) / (32f + 35 + 59 + 104)); default: return 238; } } /** * Calculate the blue value for different level. * * @param baseB Blue value of base color. * @param level Level. * @return The blue value for the level of the base color. */ public static int calculateB(int baseB, int level) { switch (level) { case 0: return 238; case 1: return baseB; case 2: return (int) (baseB * (37 + 29 + 35) / (32f + 37 + 29 + 35)); case 3: return (int) (baseB * (29 + 35) / (32f + 37 + 29 + 35)); case 4: return (int) (baseB * (35) / (32f + 37 + 29 + 35)); default: return 238; } } /** * Calculate the value for different color. * * @param baseColor Value of base color. * @param level Level. * @return The value for the level of the base color. */ public static int calculateLevelColor(int baseColor, int level) { return Color.rgb( calculateR(Color.red(baseColor), level), calculateG(Color.green(baseColor), level), calculateB(Color.blue(baseColor), level)); } /** * Calculate the shadow color face left-bottom corner. * * @param baseColor The base color. * @return The shadow color. */ public static int calculateShadowColorLeftBottom(int baseColor) { return Color.rgb( (int)(Color.red(baseColor) * 173f / 214), (int)(Color.green(baseColor) * 209f / 230), (int)(Color.blue(baseColor) * 113f / 133)); } /** * Calculate the shadow color face right-bottom corner. * * @param baseColor The base color. * @return The shadow color. */ public static int calculateShadowColorRightBottom(int baseColor) { return Color.rgb( (int)(Color.red(baseColor) * 193f / 214), (int)(Color.green(baseColor) * 219f / 230), (int)(Color.blue(baseColor) * 93f / 133)); } /** * Get the text width from its text paint and itself. * * @param textPaint The text paint of the text. * @param text The text. * @return Width, in px. */ public static int getTextWidth(Paint textPaint, String text) { Rect bounds = new Rect(); textPaint.getTextBounds(text, 0, text.length(), bounds); return bounds.width(); } /** * Get the text height from its text paint and itself. * * @param textPaint The text paint of the text. * @param text The text. * @return Height, in px. */ public static int getTextHeight(Paint textPaint, String text) { Rect bounds = new Rect(); textPaint.getTextBounds(text, 0, text.length(), bounds); return bounds.height(); } /** * Build a text paint. * * @param textSize Text size. * @param textColor The color of the text. * @param typeface Typeface of the text. * @return The paint. */ public static Paint getTextPaint(float textSize, int textColor, Typeface typeface) { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setTextSize(textSize); paint.setColor(textColor); paint.setTypeface(typeface); return paint; } /** * Get string from resource id of string. * * @param resId Resource id. * @return The string. */ public static String getString(int resId) { return GithubWidgetApplication.getAppContext().getResources().getString(resId); } /** * Get the longest streak in contributions. * * @param contributions The contributions array. * @return Longest streak, start date and end date, day(s). */ public static String[] getLongestStreak(ArrayList<Day> contributions) { int streak = 0; int longestStreak = 0; int longestStart = 0; int longestEnd = 0; for (int i = 0; i < contributions.size(); i++) { Day day = contributions.get(i); if (day.level != 0) streak++; if (day.level == 0 || i == contributions.size() - 1) { if (streak > longestStreak) { longestStreak = streak; longestEnd = day.level == 0 ? i - 1 : i; longestStart = longestEnd - longestStreak + 1; } streak = 0; } } String remarkString = getString(R.string.no_contributions_this_year); if (longestStreak != 0) { remarkString = Util.getFullMonthDayName( contributions.get(longestStart).year, contributions.get(longestStart).month, contributions.get(longestStart).day) + getString(R.string.remark_to) + Util.getFullMonthDayName( contributions.get(longestEnd).year, contributions.get(longestEnd).month, contributions.get(longestEnd).day); } String days = getString(longestStreak == 1 ? R.string.day : R.string.days); return new String[]{longestStreak + "", remarkString, days}; } /** * Get current streak. * * @param contributions The contributions array. * @return Current streak, start date and end date, day(s). */ public static String[] getCurrentStreak(ArrayList<Day> contributions) { int streak = 0; int currentStreakStart = 0; int lastStreak = -1; for (int i = contributions.size() - 1; i >= 0; i--) { if (contributions.get(i).level != 0) { streak++; } else { currentStreakStart = i + 1; break; } } for (int i = currentStreakStart - 1; i >= 0; i--) { if (contributions.get(i).level != 0) { lastStreak = i; } } String remarkString = getString(R.string.no_contributions_this_year); if (streak != 0) { remarkString = Util.getFullMonthDayName( contributions.get(currentStreakStart).year, contributions.get(currentStreakStart).month, contributions.get(currentStreakStart).day) + getString(R.string.remark_to) + Util.getFullMonthDayName( contributions.get(contributions.size() - 1).year, contributions.get(contributions.size() - 1).month, contributions.get(contributions.size() - 1).day); } else if (lastStreak != -1) { int days = contributions.size() - lastStreak + 1; remarkString = getString(R.string.last_contributed) + days + getString(R.string.days_ago); } String days = getString(streak == 1 ? R.string.day : R.string.days); return new String[]{streak + "", remarkString, days}; } /** * Get one year total. * * @param contributions The contributions array. * @return One year total, start date and end date of this year, contribution(s). */ public static String[] getOneYearTotal(ArrayList<Day> contributions) { int total = 0; for (Day day : contributions) total += day.data; String remarkString = Util.getShortDateName( contributions.get(0).year, contributions.get(0).month, contributions.get(0).day) + getString(R.string.remark_to) + Util.getShortDateName( contributions.get(contributions.size() - 1).year, contributions.get(contributions.size() - 1).month, contributions.get(contributions.size() - 1).day); String contributionsString = getString(total == 1 ? R.string.contribution : R.string.contributions); return new String[]{total + "", remarkString, contributionsString}; } /** * Get busiest day. * * @param contributions The contributions array. * @return Contributions on the busiest day, the date of it, contribution(s). */ public static String[] getBusiestDay(ArrayList<Day> contributions) { int max = 0; int maxDay = 0; for (int i = 0; i < contributions.size(); i++) { if (contributions.get(i).data > max) { max = contributions.get(i).data; maxDay = i; } } String remarkString = getString(R.string.no_contributions_this_year); if (max != 0) { remarkString = Util.getFullMonthDayName( contributions.get(maxDay).year, contributions.get(maxDay).month, contributions.get(maxDay).day); } String contributionsString = getString(max == 1 ? R.string.contribution : R.string.contributions); return new String[]{max + "", remarkString, contributionsString}; } /** * Get a 3D bitmap for contributions. * * @param context Context. * @param data Data, from http get. * @param startWeekday Start weekday. * @param baseColor Base color. * @param textColor Text color. * @param drawMonthText Whether draw the dashes and text of months. * @param drawWeekdayText Whether draw the dashes and text for weekdays. * @param containsAvatar Whether contain an avatar. Notice that this method does NOT draw an * avatar, but just leave space for it. * @return The bitmap. */ public static Bitmap get3DBitmap( Context context, String data, Weekday startWeekday, int baseColor, int textColor, boolean drawMonthText, boolean drawWeekdayText, boolean containsAvatar) { Bitmap bitmap; Canvas canvas; Paint blockPaint; Paint monthTextPaint; Paint weekdayTextPaint; Paint titlePaint; Paint numberPaint; Paint unitPaint; Paint remarkPaint; Paint dash; ArrayList<Day> contributions = getContributionsFromString(data); int bitmapWidth = Util.getScreenWidth(context); // Todo calculate the height int bitmapHeight = (int) (bitmapWidth * 0.75f); int columnNumber = Util.getContributionsColumnNumber(data); int n = columnNumber - 2; float paddingLeft = 10f; float paddingRight = 10f; float paddingTop = 10f; float paddingBottom = 10f; float emptyHeight = 5f; float a1 = 38f; float a2 = 22f; float rate = 1 / 6f; float cosa1 = (float)Math.cos(Math.toRadians(a1)); float cosa2 = (float)Math.cos(Math.toRadians(a2)); float ls = (bitmapWidth - paddingLeft - paddingRight) / ((1 / (1 + rate)) + 7 * cosa1 + (n + 1) * cosa2); float lscosa1 = (float)Math.cos(Math.toRadians(a1)) * (ls); float lscosa2 = (float)Math.cos(Math.toRadians(a2)) * (ls); float lssina1 = (float)Math.sin(Math.toRadians(a1)) * (ls); float lssina2 = (float)Math.sin(Math.toRadians(a2)) * (ls); float l = ls / (1 + rate); float lcosa1 = (float)Math.cos(Math.toRadians(a1)) * l; float lcosa2 = (float)Math.cos(Math.toRadians(a2)) * l; float lsina1 = (float)Math.sin(Math.toRadians(a1)) * l; float lsina2 = (float)Math.sin(Math.toRadians(a2)) * l; float s = l * rate; float topFaceheight = lsina1 + lsina2; float x6 = paddingLeft + lcosa2; float x0 = x6 + 7 * lscosa1; float monthDashLength = 45f; float dashTextHeight = (drawMonthText || drawWeekdayText) ? monthDashLength : 0; float maxHeight = bitmapHeight - paddingTop - topFaceheight - lssina2 * (n + 1) - 6 * lssina1 - dashTextHeight - paddingBottom; float y0 = paddingTop + topFaceheight + maxHeight + 2 * emptyHeight; int currentWeekDay = Util.getWeekDayFromDate( contributions.get(0).year, contributions.get(0).month, contributions.get(0).day); float x = x0 - ((currentWeekDay - startWeekday.v + 7) % 7) * lscosa1; float y = y0 + ((currentWeekDay - startWeekday.v + 7) % 7) * lssina1; float textHeight = l; float maxData = 0; for (Day day : contributions) maxData = Math.max(maxData, day.data); int endWeekday = (startWeekday.v - 1 + 7) % 7; float monthDashAndTextPadding = 5f; float weekdayDashAndTextPadding = 5f; float lastMonthDashEndX = 0; float lastMonthDashEndY = 0; float maxY = 0; bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG); blockPaint.setStyle(Paint.Style.FILL); monthTextPaint = Util.getTextPaint(textHeight, textColor, Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); weekdayTextPaint = Util.getTextPaint(textHeight, textColor, Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); titlePaint = Util.getTextPaint(1.5f * textHeight, textColor, Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); numberPaint = Util.getTextPaint(4 * textHeight, Util.calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); unitPaint = Util.getTextPaint(1.5f * textHeight, textColor, Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); remarkPaint = Util.getTextPaint(1.5f * textHeight, textColor, Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); dash = new Paint(Paint.ANTI_ALIAS_FLAG); dash.setARGB(255, 0, 0,0); dash.setStyle(Paint.Style.STROKE); dash.setColor(textColor); dash.setPathEffect(new DashPathEffect(new float[] {5, 5}, 0)); int lastMonth = contributions.get(0).month; for (int i = 0; i < contributions.size(); i++) { Day day = contributions.get(i); float height; if (day.data == 0) height = emptyHeight; else height = maxHeight * day.data / maxData + 2 * emptyHeight; // face right-bottom corner blockPaint.setColor( Util.calculateShadowColorRightBottom( Util.calculateLevelColor(baseColor, day.level))); Path path = new Path(); path.moveTo(x, y); path.lineTo(x + lcosa1, y - lsina1); path.lineTo(x + lcosa1, y - lsina1 - height); path.lineTo(x, y - height); path.lineTo(x, y); canvas.drawPath(path, blockPaint); // face left-bottom corner blockPaint.setColor( Util.calculateShadowColorLeftBottom( Util.calculateLevelColor(baseColor, day.level))); path = new Path(); path.moveTo(x, y); path.lineTo(x - lcosa2, y - lsina2); path.lineTo(x - lcosa2, y - lsina2 - height); path.lineTo(x, y - height); path.lineTo(x, y); canvas.drawPath(path, blockPaint); // face top blockPaint.setColor(Util.calculateLevelColor(baseColor, day.level)); path = new Path(); path.moveTo(x, y - height); path.lineTo(x + lcosa1, y - lsina1 - height); path.lineTo(x + lcosa1 - lcosa2, y - lsina1 - height - lsina2); path.lineTo(x - lcosa2, y - lsina2 - height); path.lineTo(x, y - height); canvas.drawPath(path, blockPaint); if (i == contributions.size() - 1) break; currentWeekDay = (currentWeekDay + 1) % 7; if (currentWeekDay == startWeekday.v) { // another column x = x + 6 * lscosa1 + lscosa2; y = y - 6 * lssina1 + lssina2; } else { x -= lscosa1; y += lssina1; lastMonthDashEndX = x - lcosa2; lastMonthDashEndY = y - lsina2 + monthDashLength; if (currentWeekDay == endWeekday && day.month != lastMonth && drawMonthText) { canvas.drawLine(x - lcosa2, y - lsina2, lastMonthDashEndX, lastMonthDashEndY, dash); canvas.drawText( Util.getShortMonthName(day.year, day.month, day.day), lastMonthDashEndX + monthDashAndTextPadding, lastMonthDashEndY, monthTextPaint); lastMonth = day.month; } } maxY = Math.max(y, maxY); } if (drawMonthText || drawWeekdayText) maxY = lastMonthDashEndY; if (drawWeekdayText) { int lastWeekdaysNumber = Util.getLastWeekDaysNumber(contributions, startWeekday); x += (lastWeekdaysNumber - 1) * lscosa1; y -= (lastWeekdaysNumber - 1) * lssina1; float dashLength = lastMonthDashEndY - (y + 4 * lssina1); for (int i = 2; i >= 0; i--) { int drewWeekday = (startWeekday.v + 1 + 2 * i) % 7; String weekdayString = Util.getWeekdayFirstLetter(drewWeekday); canvas.drawText( weekdayString, x - 2 * i * lscosa1 - Util.getTextWidth(weekdayTextPaint, weekdayString) - weekdayDashAndTextPadding, y + (1 + 2 * i) * lssina1 + dashLength, weekdayTextPaint); if (2 * i >= lastWeekdaysNumber) { Path path = new Path(); path.moveTo( x - 2 * i * lscosa1, y + (1 + 2 * i) * lssina1 + dashLength); path.lineTo(x - 2 * i * lscosa1, y + 2 * i * lssina1); // path.lineTo( // x - 2 * i * lscosa1 - lscosa2, // y + 2 * i * lssina1 - lssina2); canvas.drawPath(path, dash); } else { canvas.drawLine( x - 2 * i * lscosa1, y + (1 + 2 * i) * lssina1 + dashLength, x - 2 * i * lscosa1, y + 2 * i * lssina1, dash); } } } float partPadding = 2 * textHeight; float textLeftPadding = 20f; float titleAndNumberPadding = 8f; float numberAndRemarkPadding = 10f; float unitAndRemarkPadding = 5f; float avatarWidth = containsAvatar ? bitmapWidth / 4.5f : 0; // draw current streak text String[] currentStreaks = Util.getCurrentStreak(contributions); float numberHeight = Util.getTextHeight(numberPaint, currentStreaks[0]); float numberWidth = Util.getTextWidth(numberPaint, currentStreaks[0]); float titleWidth = Util.getTextWidth(titlePaint, Util.getString(R.string.current_streak)); float remarkHeight = Util.getTextHeight(remarkPaint, currentStreaks[1]); canvas.drawText(Util.getString(R.string.current_streak), textLeftPadding, maxY - numberHeight - titleAndNumberPadding, titlePaint); canvas.drawText(currentStreaks[0], textLeftPadding + titleWidth - numberWidth, maxY, numberPaint); canvas.drawText(currentStreaks[1], textLeftPadding + titleWidth + numberAndRemarkPadding, maxY, remarkPaint); canvas.drawText(currentStreaks[2], textLeftPadding + titleWidth + numberAndRemarkPadding, maxY - remarkHeight - unitAndRemarkPadding, unitPaint); // draw longest streak text String[] longestStreaks = Util.getLongestStreak(contributions); numberHeight = Util.getTextHeight(numberPaint, longestStreaks[0]); numberWidth = Util.getTextWidth(numberPaint, longestStreaks[0]); titleWidth = Util.getTextWidth(titlePaint, Util.getString(R.string.longest_streak)); remarkHeight = Util.getTextHeight(remarkPaint, longestStreaks[1]); canvas.drawText(Util.getString(R.string.longest_streak), textLeftPadding, maxY - 2 * numberHeight - 2 * titleAndNumberPadding - partPadding, titlePaint); canvas.drawText(longestStreaks[0], textLeftPadding + titleWidth - numberWidth, maxY - numberHeight - titleAndNumberPadding - partPadding, numberPaint); canvas.drawText(longestStreaks[1], textLeftPadding + titleWidth + numberAndRemarkPadding, maxY - numberHeight - titleAndNumberPadding - partPadding, remarkPaint); canvas.drawText(longestStreaks[2], textLeftPadding + titleWidth + numberAndRemarkPadding, maxY - remarkHeight - unitAndRemarkPadding - numberHeight - titleAndNumberPadding - partPadding, unitPaint); // draw total text String[] totalStreaks = Util.getOneYearTotal(contributions); String[] busiestStreaks = Util.getBusiestDay(contributions); numberHeight = Util.getTextHeight(numberPaint, totalStreaks[0]); numberWidth = Util.getTextWidth(numberPaint, totalStreaks[0]); int titleHeight = Util.getTextHeight(titlePaint, Util.getString(R.string.one_year_total)); titleWidth = Util.getTextWidth(titlePaint, Util.getString(R.string.one_year_total)); remarkHeight = Util.getTextHeight(remarkPaint, totalStreaks[1]); int unitAndRemarkWidth = Util.getTextWidth(remarkPaint, totalStreaks[1]); unitAndRemarkWidth = Math.max(unitAndRemarkWidth, Util.getTextWidth(unitPaint, totalStreaks[2])); unitAndRemarkWidth = Math.max(unitAndRemarkWidth, Util.getTextWidth(remarkPaint, busiestStreaks[1])); unitAndRemarkWidth = Math.max(unitAndRemarkWidth, Util.getTextWidth(unitPaint, busiestStreaks[2])); canvas.drawText(Util.getString(R.string.one_year_total), bitmapWidth - paddingRight - unitAndRemarkWidth - numberAndRemarkPadding - titleWidth - avatarWidth, paddingTop + titleHeight, titlePaint); canvas.drawText(totalStreaks[0], bitmapWidth - paddingRight - unitAndRemarkWidth - numberAndRemarkPadding - numberWidth - avatarWidth, paddingTop + titleHeight + titleAndNumberPadding + numberHeight, numberPaint); canvas.drawText(totalStreaks[1], bitmapWidth - paddingRight - unitAndRemarkWidth - avatarWidth, paddingTop + titleHeight + titleAndNumberPadding + numberHeight, remarkPaint); canvas.drawText(totalStreaks[2], bitmapWidth - paddingRight - unitAndRemarkWidth - avatarWidth, paddingTop + titleHeight + titleAndNumberPadding + numberHeight - remarkHeight - unitAndRemarkPadding, remarkPaint); // draw busiest day numberHeight = Util.getTextHeight(numberPaint, busiestStreaks[0]); numberWidth = Util.getTextWidth(numberPaint, busiestStreaks[0]); titleHeight = Util.getTextHeight(titlePaint, Util.getString(R.string.busiest_day)); titleWidth = Util.getTextWidth(titlePaint, Util.getString(R.string.busiest_day)); remarkHeight = Util.getTextHeight(remarkPaint, busiestStreaks[1]); canvas.drawText(Util.getString(R.string.busiest_day), bitmapWidth - paddingRight - unitAndRemarkWidth - numberAndRemarkPadding - titleWidth - avatarWidth, paddingTop + titleHeight + titleAndNumberPadding + numberHeight + partPadding, titlePaint); canvas.drawText(busiestStreaks[0], bitmapWidth - paddingRight - unitAndRemarkWidth - numberAndRemarkPadding - numberWidth - avatarWidth, paddingTop + titleHeight + 2 * titleAndNumberPadding + 2 * numberHeight + partPadding, numberPaint); canvas.drawText(busiestStreaks[1], bitmapWidth - paddingRight - unitAndRemarkWidth - avatarWidth, paddingTop + titleHeight + 2 * titleAndNumberPadding + 2 * numberHeight + partPadding, remarkPaint); canvas.drawText(busiestStreaks[2], bitmapWidth - paddingRight - unitAndRemarkWidth - avatarWidth, paddingTop + titleHeight + 2 * titleAndNumberPadding + 2 * numberHeight - remarkHeight - unitAndRemarkPadding + partPadding, remarkPaint); return bitmap; } /** * Get a bitmap to guide user to set their user name. * * @param context Context. * @param baseColor Base color. * @return The bitmap. */ public static Bitmap getInputUserNameBitmap(Context context, int baseColor, int bitmapHeight) { Bitmap bitmap; Canvas canvas; Paint paint = getTextPaint(40f, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); int bitmapWidth = getScreenWidth(context); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); int xPos = (canvas.getWidth() / 2) - getTextWidth(paint, getString(R.string.click_to_set)) / 2; int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)) ; canvas.drawText(getString(R.string.click_to_set), xPos, yPos, paint); return bitmap; } /** * Get the bitmap of contributions sum. * * @param context Context. * @param baseColor Base color. * @param sum Sum. * @return The bitmap. */ public static Bitmap getContributionsSumBitmap(Context context, int baseColor, int sum) { Bitmap bitmap; Canvas canvas; Paint paint = getTextPaint(30f, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); int bitmapWidth = dp2px(60); int bitmapHeight = dp2px(20); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); int xPos = (canvas.getWidth() / 2) - getTextWidth(paint, sum + "") / 2; int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)) ; canvas.drawText(sum + "", xPos, yPos, paint); return bitmap; } /** * Decimal to hex. * * @param dec Decimal value. * @return The hex value. */ public static String decToHex(int dec) { String hex = Integer.toHexString(dec); return hex.length() == 1 ? "0" + hex : hex; } /** * Create a bitmap where there are sum and english. * * @param context Context. * @param baseColor Base color. * @param sum Sum. * @param bitmapWidth Width. * @param bitmapHeight Height. * @return */ public static Bitmap getContributionsSumWithLetterBitmap( Context context, int baseColor, int sum, int bitmapWidth, int bitmapHeight) { Bitmap bitmap; Canvas canvas; Paint mainPaint = getTextPaint(WIDGET_2_NUMBER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); Paint subPaint = getTextPaint(WIDGET_2_LETTER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); int xPos = (canvas.getWidth() / 2) - getTextWidth(mainPaint, sum + "") / 2; int yPos = getTextHeight(mainPaint, sum + ""); canvas.drawText(sum + "", xPos, yPos, mainPaint); xPos = (canvas.getWidth() / 2) - getTextWidth(subPaint, getString(R.string.one_year)) / 2; canvas.drawText(getString(R.string.one_year), xPos, canvas.getHeight() - WIDGET_2_LETTER_PADDING_BOTTOM, subPaint); return bitmap; } /** * Get target dimen in px. * * @param resId Resource id. * @return Px. */ public static float getDimen(int resId) { return GithubWidgetApplication.getAppContext().getResources().getDimensionPixelSize(resId); } /** * Get today contributions from string. * * @param data Data in string. * @return Contributions of today. */ public static int getContributionsToday(String data) { int index = data.lastIndexOf(DATA_STRING); if (index != -1) { int dataEndPos = data.indexOf("\"", index + DATA_STRING.length()); String dataString = data.substring(index + DATA_STRING.length(), dataEndPos); return Integer.valueOf(dataString); } return 0; } /** * Create a bitmap where there are contributions of today and english. * * @param context Context. * @param baseColor Base color. * @param today Sum. * @param bitmapWidth Width. * @param bitmapHeight Height. * @return The bitmap. */ public static Bitmap getContributionsTodayWithLetterBitmap( Context context, int baseColor, int today, int bitmapWidth, int bitmapHeight) { Bitmap bitmap; Canvas canvas; Paint mainPaint = getTextPaint(WIDGET_2_NUMBER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); Paint subPaint = getTextPaint(WIDGET_2_LETTER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); int xPos = (canvas.getWidth() / 2) - getTextWidth(mainPaint, today + "") / 2; int yPos = getTextHeight(mainPaint, today + ""); canvas.drawText(today + "", xPos, yPos, mainPaint); xPos = (canvas.getWidth() / 2) - getTextWidth(subPaint, getString(R.string.today)) / 2; canvas.drawText(getString(R.string.today), xPos, canvas.getHeight() - WIDGET_2_LETTER_PADDING_BOTTOM, subPaint); return bitmap; } /** * Create a bitmap where there are current streak and english. * * @param context Context. * @param baseColor Base color. * @param days Sum. * @param bitmapWidth Width. * @param bitmapHeight Height. * @return The bitmap. */ public static Bitmap getCurrentStreakWithLetterBitmap( Context context, int baseColor, int days, int bitmapWidth, int bitmapHeight) { Bitmap bitmap; Canvas canvas; Paint mainPaint = getTextPaint(WIDGET_2_NUMBER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); Paint subPaint = getTextPaint(WIDGET_2_LETTER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); int xPos = (canvas.getWidth() / 2) - getTextWidth(mainPaint, days + "") / 2; int yPos = getTextHeight(mainPaint, days + ""); canvas.drawText(days + "", xPos, yPos, mainPaint); xPos = (canvas.getWidth() / 2) - getTextWidth(subPaint, getString(R.string.current)) / 2; canvas.drawText(getString(R.string.current), xPos, canvas.getHeight() - WIDGET_2_LETTER_PADDING_BOTTOM, subPaint); return bitmap; } /** * Get the motto bitmap. * * @param context Context. * @param baseColor Base color. * @param bitmapWidth Width of bitmap. * @param bitmapHeight Height of bitmap. * @return The bitmap. */ public static Bitmap getMottoBitmap( Context context, int baseColor, int bitmapWidth, int bitmapHeight) { Bitmap bitmap; Canvas canvas; float textHeight = 40f; float textPadding = 5f; float xPos = 0; Paint mainPaint = getTextPaint(textHeight, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); String content = SettingsManager.getMotto(); if ("".equals(content) && SettingsManager.getUserName() != null) content = SettingsManager.getUserName(); boolean isTwoLines = content.contains("\n"); if (isTwoLines) { canvas.drawText( content.substring(0, content.indexOf("\n")), xPos, canvas.getHeight() / 2 - textPadding, mainPaint); canvas.drawText( content.substring(content.indexOf("\n") + 1, content.length()), xPos, canvas.getHeight() / 2 + textPadding + textHeight, mainPaint); } else { canvas.drawText( content, xPos, canvas.getHeight() / 2 + textHeight / 2, mainPaint); } return bitmap; } /** * At first, I wanna calculate the diff of followers increase a day. * But I leave it to Todo. * * @param result The result from https://api.github.com/users/username. * @return The string of followers. */ public static String writeFollowers(String result) { SharedPreferences.Editor editor = PreferenceManager .getDefaultSharedPreferences(GithubWidgetApplication.getAppContext()).edit(); JSONObject jsonObject = null; try { jsonObject = new JSONObject(result); int lastFollowers = SettingsManager.getFollowers(); long lastUpdateFollowersTime = SettingsManager.getLastUpdateFollowersTime(); int nowFollowers = jsonObject.getInt("followers"); if (lastUpdateFollowersTime == -1 || lastFollowers == -1) { // first time SettingsManager.setFollowers(nowFollowers); SettingsManager.setLastUpdateFollowersTime( Calendar.getInstance().getTime().getTime()); return nowFollowers + ""; } else { int diff = 0; if (lastFollowers != -1) diff = nowFollowers - lastFollowers; if (diff > 0) { return shortNumber(nowFollowers) + "+" + diff; } else if (diff < 0) { return shortNumber(nowFollowers) + "-" + (-diff); } else { return shortNumber(nowFollowers) + ""; } } } catch (JSONException e) { e.printStackTrace(); int lastFollowers = SettingsManager.getFollowers(); if (lastFollowers != -1) return shortNumber(lastFollowers) + ""; else return ""; } finally { editor.commit(); } } /** * 1000 -> 1k, 1100->1.1k * * @param number The input number. * @return The string. */ public static String shortNumber(int number) { if (number >= 1000) { int hundred = number % 1000 / 100; if (hundred != 0) return String.format("%.1f", number / 1000) + "k"; else return (number / 1000) + "k"; } else return number + ""; } /** * Create a bitmap where there are followers and english. * * @param context Context. * @param baseColor Base color. * @param followers String of followers. * @param bitmapWidth Width. * @param bitmapHeight Height. * @return The bitmap. */ public static Bitmap getFollowersWithLetterBitmap( Context context, int baseColor, String followers, int bitmapWidth, int bitmapHeight) { Bitmap bitmap; Canvas canvas; Paint mainPaint = getTextPaint(WIDGET_2_NUMBER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); Paint subPaint = getTextPaint(WIDGET_2_LETTER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); // I decide not to draw this if (followers.contains("+")) followers = followers.substring(0, followers.indexOf("+")); if (followers.contains("-")) followers = followers.substring(0, followers.indexOf("-")); int xPos = (canvas.getWidth() / 2) - getTextWidth(mainPaint, followers + "") / 2; int yPos = getTextHeight(mainPaint, followers + ""); canvas.drawText(followers + "", xPos, yPos, mainPaint); xPos = (canvas.getWidth() / 2) - getTextWidth(subPaint, getString(R.string.followers)) / 2; canvas.drawText(getString(R.string.followers), xPos, canvas.getHeight() - WIDGET_2_LETTER_PADDING_BOTTOM, subPaint); return bitmap; } /** * Create a bitmap where there are stars and english. * * @param context Context. * @param baseColor Base color. * @param stars String of stars. * @param bitmapWidth Width. * @param bitmapHeight Height. * @return The bitmap. */ public static Bitmap getStarsWithLetterBitmap( Context context, int baseColor, String stars, int bitmapWidth, int bitmapHeight) { Bitmap bitmap; Canvas canvas; Paint mainPaint = getTextPaint(WIDGET_2_NUMBER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); Paint subPaint = getTextPaint(WIDGET_2_LETTER_HEIGHT, calculateLevelColor(baseColor, 4), Typeface.createFromAsset(context.getAssets(), "fonts/Lato-Light.ttf")); bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); int xPos = (canvas.getWidth() / 2) - getTextWidth(mainPaint, stars + "") / 2; int yPos = getTextHeight(mainPaint, stars + ""); canvas.drawText(stars + "", xPos, yPos, mainPaint); xPos = (canvas.getWidth() / 2) - getTextWidth(subPaint, getString(R.string.stars)) / 2; canvas.drawText(getString(R.string.stars), xPos, canvas.getHeight() - WIDGET_2_LETTER_PADDING_BOTTOM, subPaint); return bitmap; } /** * Write the star update time and get the string of stars. * * @param result The string of result. * @return The string of stars. */ public static String writeStars(String result) { SharedPreferences.Editor editor = PreferenceManager .getDefaultSharedPreferences(GithubWidgetApplication.getAppContext()).edit(); JSONArray jsonArray = null; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String nowDateString = format.format(Calendar.getInstance().getTime()); boolean thisIsANewDay = false; if (SettingsManager.getLastUpdateStarsDate() == null || !SettingsManager.getLastUpdateStarsDate().equals(nowDateString)) { thisIsANewDay = true; } if (thisIsANewDay) SettingsManager.setTodayStars(0); try { jsonArray = new JSONArray(result); String lastId = SettingsManager.getLastUpdateStarsId(); int stars = SettingsManager.getTodayStars(); boolean first = true; for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); if (jsonObject == null) continue; // if we found the record we already deal if (jsonObject.has("id") && jsonObject.getString("id").equals(lastId)) break; // record the first id we already deal if (first) { if (jsonObject.has("id")) { SettingsManager.setLastUpdateStarsId(jsonObject.getString("id")); SettingsManager.setLastUpdateStarsDate( jsonObject.getString("created_at").substring(0, 10)); first = false; } } // whether this event is created today if (nowDateString.equals(jsonObject.getString("created_at").substring(0, 10))) { // whether this is a watcher event if (jsonObject.has("type") && jsonObject.getString("type").equals("WatchEvent")) { JSONObject payload = jsonObject.getJSONObject("payload"); // whether this is a star event if (payload.has("action") && payload.getString("action").equals("started")) { JSONObject repo = jsonObject.getJSONObject("repo"); // whether the repository starred is belong to user if (repo != null && repo.has("name")) { String repoName = repo.getString("name"); if (repoName != null) repoName = repoName.toLowerCase(); String userName = SettingsManager.getUserName(); if (userName != null) userName = userName.toLowerCase(); if (repoName != null && userName != null) { if (repoName.indexOf(userName) == 0) { stars++; } } } } } } } SettingsManager.setTodayStars(stars); return "+" + stars; } catch (JSONException e) { e.printStackTrace(); return "+" + 0; } finally { editor.commit(); } } /** * Update a motto on a widget. * * @param c The class of the widget. * @param remoteViewsId The layout resourece id of the widget. * @param context Context. * @param bitmapWidth Motto width. * @param bitmapHeight Motto height. */ public static void updateMotto(Class c, int remoteViewsId, Context context, int bitmapWidth, int bitmapHeight) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), remoteViewsId); remoteViews.setImageViewBitmap(R.id.motto, Util.getMottoBitmap(context, SettingsManager.getBaseColor(), bitmapWidth, bitmapHeight)); AppWidgetManager.getInstance(context).updateAppWidget( new ComponentName(context, c), remoteViews); } /** * Set a alarm to wake the service. * * @param context Context. * @param servicePendingIntent PendingIntent for service. */ public static void addAlarmService(Context context, PendingIntent servicePendingIntent) { if (BuildConfig.DEBUG) Log.d("GithubWidget", "----------------------------------------" + "Add alarm service"); final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); final Calendar current = Calendar.getInstance(); current.add(Calendar.MILLISECOND, SettingsManager.getUpdateTime()); final Intent i = new Intent(context, GithubWidgetService.class); if (servicePendingIntent == null) { servicePendingIntent = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); } m.setRepeating(AlarmManager.RTC, current.getTime().getTime(), SettingsManager.getUpdateTime(), servicePendingIntent); } /** * Check whether a pendingIntent is register in alarmManager. * There may be something wrong in this method. * * @param context The context. * @param servicePendingIntent The pendingIntent; * @return Result. */ public static boolean checkAlarmService(Context context, PendingIntent servicePendingIntent) { final Intent i = new Intent(context, GithubWidgetService.class); return PendingIntent.getService(context, 0, i, PendingIntent.FLAG_NO_CREATE) != null; } /** * Get the login cookie. * * @return The login cookie. */ public static String getLoginCookie() { return CookieManager.getInstance().getCookie(Util.getString(R.string.login_url)); } /** * Whether the user has already signed in. * * @return Result. */ public static boolean getLoggedIn() { String cookie = getLoginCookie(); try { return cookie != null && cookie.split(";")[0].equals("logged_in=yes"); } catch (PatternSyntaxException p) { p.printStackTrace(); return false; } } /** * Clean the cookies. */ @SuppressWarnings("deprecation") public static void clearCookies() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { CookieManager.getInstance().removeAllCookies(null); CookieManager.getInstance().flush(); } else { CookieSyncManager localCookieSyncManager = CookieSyncManager.createInstance(GithubWidgetApplication.getAppContext()); localCookieSyncManager.startSync(); CookieManager localCookieManager = CookieManager.getInstance(); localCookieManager.removeAllCookie(); localCookieManager.removeSessionCookie(); localCookieSyncManager.stopSync(); localCookieSyncManager.sync(); } } /** * Log. * * @param content The content. */ public static void log(String content) { if (BuildConfig.DEBUG) Log.d(TAG, content); } /** * Get the bitmap of the trending sub view in list view in widget. * * @param index The index of the trending. * @return The bitmap. */ public static Bitmap getTrendingBitmap(int index) { Bitmap bitmap = Bitmap.createBitmap( (int) (dp2px(280)), (int) getDimen(R.dimen.list_view_content_item_height), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint ownerPaint = getTextPaint(25f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); Paint repoPaint = getTextPaint(25f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); repoPaint.setFakeBoldText(true); Paint contentPaint = getTextPaint(18f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); Paint cornerPaint = getTextPaint(18f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); Paint cornerNumberPaint = getTextPaint(18f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); // cornerNumberPaint.setFakeBoldText(true); Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dividerPaint.setColor(ContextCompat.getColor( GithubWidgetApplication.getAppContext(), R.color.divider_color)); canvas.drawLine(0, canvas.getHeight(), canvas.getWidth(), canvas.getHeight(), dividerPaint); if (SettingsManager.getListViewContents() == null) { // illegal return bitmap; } float titlePaddingTop = 10f; float titlePaddingLeft = 10f; float titlePaddingRight = 10f; float contentPaddingTop = 10f; float contentPaddingLeft = 10f; float contentPaddingRight = 10f; float contentPaddingBottom = 10f; float cornerPaddingTop = 10f; float cornerPaddingRight = 10f; float titleCenterY = (int) ((canvas.getHeight() / 2) - ((repoPaint.descent() + repoPaint.ascent()) / 2)); HashMap<String, String> content = SettingsManager.getListViewContents().get(index); String ownerString = content.get("title").substring(0, content.get("title").indexOf("/") + 1); String originRepoString = content.get("title").substring(content.get("title").indexOf("/") + 1, content.get("title").length()); int i = 1; String showRepoString = originRepoString; if (titlePaddingLeft + titlePaddingRight + getTextWidth(ownerPaint, ownerString) + getTextWidth(repoPaint, showRepoString) > dp2px(280)) { showRepoString = originRepoString.substring(0, originRepoString.length() - i) + getString(R.string.dots);; while (titlePaddingLeft + titlePaddingRight + getTextWidth(ownerPaint, ownerString) + getTextWidth(repoPaint, showRepoString) > dp2px(280)) { i++; showRepoString = originRepoString.substring(0, originRepoString.length() - i) + getString(R.string.dots); if (i == originRepoString.length()) break; } } canvas.drawText(ownerString, titlePaddingLeft, titleCenterY, ownerPaint); canvas.drawText(showRepoString, getTextWidth(ownerPaint, ownerString) + titlePaddingLeft, titleCenterY, repoPaint); String fullContentString = content.get("content"); String contentString = ""; boolean enough = false; i = 0; while (contentPaddingLeft + contentPaddingRight + getTextWidth(contentPaint, contentString + getString(R.string.dots)) < dp2px(280)) { if (i >= fullContentString.length()) { enough = true; break; } contentString += fullContentString.charAt(i); i++; } if (!enough) contentString = contentString.substring(0, contentString.length() - 1) + getString(R.string.dots); canvas.drawText(contentString, contentPaddingLeft, canvas.getHeight() - contentPaddingBottom, contentPaint); String cornerString = content.get("corner"); canvas.drawText(cornerString, canvas.getWidth() - cornerPaddingRight - getTextWidth(cornerPaint, cornerString), cornerPaddingTop + getTextHeight(cornerPaint, cornerString), cornerPaint); return bitmap; } /** * Get the bitmap of received-event in list view in widget. * * @param index The index of the received-events. * @return The bitmap. */ public static Bitmap getReceivedEventBitmap(int index) { Bitmap bitmap = Bitmap.createBitmap( (int) (dp2px(280)), (int) getDimen(R.dimen.list_view_content_item_height), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint titlePaint = getTextPaint(25f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); Paint contentPaint = getTextPaint(18f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); Paint cornerPaint = getTextPaint(18f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dividerPaint.setColor(ContextCompat.getColor( GithubWidgetApplication.getAppContext(), R.color.divider_color)); canvas.drawLine(0, canvas.getHeight(), canvas.getWidth(), canvas.getHeight(), dividerPaint); if (SettingsManager.getListViewContents() == null) { // illegal return bitmap; } float titlePaddingTop = 10f; float titlePaddingLeft = 10f; float titlePaddingRight = 10f; float contentPaddingTop = 10f; float contentPaddingLeft = 10f; float contentPaddingRight = 10f; float contentPaddingBottom = 10f; float cornerPaddingTop = 10f; float cornerPaddingRight = 10f; float titleCenterY = (int) ((canvas.getHeight() / 2) - ((titlePaint.descent() + titlePaint.ascent()) / 2)); HashMap<String, String> content = SettingsManager.getListViewContents().get(index); String originTitleString = content.get("title"); int i = 1; String showTitleString = originTitleString; if (titlePaddingLeft + titlePaddingRight + getTextWidth(titlePaint, showTitleString) > dp2px(280)) { showTitleString = originTitleString.substring(0, originTitleString.length() - i) + getString(R.string.dots);; while (titlePaddingLeft + titlePaddingRight + getTextWidth(titlePaint, showTitleString) > dp2px(280)) { i++; showTitleString = originTitleString.substring(0, originTitleString.length() - i) + getString(R.string.dots); if (i == originTitleString.length()) break; } } canvas.drawText(showTitleString, titlePaddingLeft, titleCenterY, titlePaint); String originContentString = content.get("content"); i = 1; String showContentString = originContentString; if (titlePaddingLeft + titlePaddingRight + getTextWidth(titlePaint, showContentString) > dp2px(280)) { showContentString = originContentString.substring(0, originContentString.length() - i) + getString(R.string.dots);; while (titlePaddingLeft + titlePaddingRight + getTextWidth(titlePaint, showContentString) > dp2px(280)) { i++; showContentString = originContentString.substring(0, originContentString.length() - i) + getString(R.string.dots); if (i == originContentString.length()) break; } } canvas.drawText(showContentString, contentPaddingLeft, canvas.getHeight() - contentPaddingBottom, contentPaint); String cornerString = content.get("corner"); canvas.drawText(cornerString, canvas.getWidth() - cornerPaddingRight - getTextWidth(cornerPaint, cornerString), cornerPaddingTop + getTextHeight(cornerPaint, cornerString), cornerPaint); return bitmap; } /** * Get the loading view in the list view of widget. * * @return The bitmap. */ public static Bitmap getLoadingBitmap() { Bitmap bitmap = Bitmap.createBitmap( (int) (dp2px(280)), (int) getDimen(R.dimen.list_view_content_item_height), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint loadingPaint = getTextPaint(25f, calculateLevelColor(SettingsManager.getBaseColor(), 4), Typeface.createFromAsset(GithubWidgetApplication.getAppContext().getAssets(), "fonts/Lato-Light.ttf")); if (SettingsManager.getListViewContents() == null) { // illegal return bitmap; } float titleCenterY = (int) ((canvas.getHeight() / 2) - ((loadingPaint.descent() + loadingPaint.ascent()) / 2)); canvas.drawText(getString(R.string.loading), canvas.getWidth() / 2 - getTextWidth(loadingPaint, getString(R.string.loading)) / 2, titleCenterY, loadingPaint); return bitmap; } /** * Transform the UTC time to the local time zone. * * @param string Input time. * @return Output time. */ public static String getTime(String string) { string = string.replace("T", " "); string = string.replace("Z", ""); try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = simpleDateFormat.parse(string); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return getShortDateName( calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH)) + " " + calendar.get(Calendar.HOUR_OF_DAY) + ":" + (calendar.get(Calendar.MINUTE) < 10 ? "0" + calendar.get(Calendar.MINUTE) : calendar.get(Calendar.MINUTE)); } catch (ParseException e) { e.printStackTrace(); return string; } } public static final String[] keyWordsStart = new String[]{"<a href", "</a>", "<img"}; public static final String[] keyWordsEnd = new String[]{">", ">", ">"}; public static String deleteUselessString(String input) { StringBuilder builder = new StringBuilder(input); for (int i = 0; i < keyWordsStart.length; i++) { while (true) { int index = builder.indexOf(keyWordsStart[i]); if (index != -1) { int end = builder.indexOf(keyWordsEnd[i], index); builder.delete(index, end + 1); } else { break; } } } return builder.toString(); } public final static String SHOW_DATA = "\n" + "<svg width=\"721\" height=\"110\" class=\"js-calendar-graph-svg\">\n" + " <g transform=\"translate(20, 20)\">\n" + " <g transform=\"translate(0, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#1e6823\" data-count=\"46\" data-date=\"2015-04-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-04-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-04-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2015-04-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-04-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2015-05-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-05-02\"/>\n" + " </g>\n" + " <g transform=\"translate(13, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-05-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-05-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-05-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-05-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-05-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-05-09\"/>\n" + " </g>\n" + " <g transform=\"translate(26, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-05-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-05-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-05-16\"/>\n" + " </g>\n" + " <g transform=\"translate(39, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-05-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-05-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-05-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-05-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-05-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-05-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-23\"/>\n" + " </g>\n" + " <g transform=\"translate(52, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-05-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"21\" data-date=\"2015-05-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-05-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-05-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-05-30\"/>\n" + " </g>\n" + " <g transform=\"translate(65, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-05-31\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-06-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-06-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2015-06-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2015-06-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-06-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-06-06\"/>\n" + " </g>\n" + " <g transform=\"translate(78, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-06-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-06-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#8cc665\" data-count=\"20\" data-date=\"2015-06-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-06-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-06-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-06-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-06-13\"/>\n" + " </g>\n" + " <g transform=\"translate(91, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-06-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2015-06-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#8cc665\" data-count=\"15\" data-date=\"2015-06-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-06-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-06-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"17\" data-date=\"2015-06-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-06-20\"/>\n" + " </g>\n" + " <g transform=\"translate(104, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2015-06-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-06-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-06-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-06-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-06-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-06-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#1e6823\" data-count=\"34\" data-date=\"2015-06-27\"/>\n" + " </g>\n" + " <g transform=\"translate(117, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"20\" data-date=\"2015-06-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-06-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#1e6823\" data-count=\"33\" data-date=\"2015-06-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2015-07-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-07-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-07-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-07-04\"/>\n" + " </g>\n" + " <g transform=\"translate(130, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"18\" data-date=\"2015-07-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#44a340\" data-count=\"26\" data-date=\"2015-07-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-07-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-07-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2015-07-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-07-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-07-11\"/>\n" + " </g>\n" + " <g transform=\"translate(143, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-07-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-07-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"24\" data-date=\"2015-07-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2015-07-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-07-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-07-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-07-18\"/>\n" + " </g>\n" + " <g transform=\"translate(156, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-07-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-07-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2015-07-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-07-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"20\" data-date=\"2015-07-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2015-07-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-07-25\"/>\n" + " </g>\n" + " <g transform=\"translate(169, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-07-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-07-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-07-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-07-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-07-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-07-31\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-08-01\"/>\n" + " </g>\n" + " <g transform=\"translate(182, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#1e6823\" data-count=\"45\" data-date=\"2015-08-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"18\" data-date=\"2015-08-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-08-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#1e6823\" data-count=\"33\" data-date=\"2015-08-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-08-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-08-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2015-08-08\"/>\n" + " </g>\n" + " <g transform=\"translate(195, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#1e6823\" data-count=\"43\" data-date=\"2015-08-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2015-08-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-08-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-08-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-08-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"20\" data-date=\"2015-08-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2015-08-15\"/>\n" + " </g>\n" + " <g transform=\"translate(208, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-08-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-08-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-08-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2015-08-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-08-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2015-08-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#44a340\" data-count=\"27\" data-date=\"2015-08-22\"/>\n" + " </g>\n" + " <g transform=\"translate(221, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#44a340\" data-count=\"22\" data-date=\"2015-08-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-08-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-08-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-08-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-08-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-08-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-08-29\"/>\n" + " </g>\n" + " <g transform=\"translate(234, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#44a340\" data-count=\"22\" data-date=\"2015-08-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"21\" data-date=\"2015-08-31\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-09-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#44a340\" data-count=\"22\" data-date=\"2015-09-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-09-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-09-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-09-05\"/>\n" + " </g>\n" + " <g transform=\"translate(247, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-09-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-09-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"28\" data-date=\"2015-09-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"15\" data-date=\"2015-09-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-09-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-09-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-09-12\"/>\n" + " </g>\n" + " <g transform=\"translate(260, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2015-09-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-09-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-09-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-09-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-09-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"15\" data-date=\"2015-09-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#44a340\" data-count=\"22\" data-date=\"2015-09-19\"/>\n" + " </g>\n" + " <g transform=\"translate(273, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#1e6823\" data-count=\"33\" data-date=\"2015-09-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2015-09-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-09-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-09-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-09-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"17\" data-date=\"2015-09-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#44a340\" data-count=\"28\" data-date=\"2015-09-26\"/>\n" + " </g>\n" + " <g transform=\"translate(286, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#44a340\" data-count=\"30\" data-date=\"2015-09-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"19\" data-date=\"2015-09-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2015-09-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"21\" data-date=\"2015-09-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"15\" data-date=\"2015-10-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2015-10-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-10-03\"/>\n" + " </g>\n" + " <g transform=\"translate(299, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-10-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-10-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#8cc665\" data-count=\"19\" data-date=\"2015-10-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#1e6823\" data-count=\"40\" data-date=\"2015-10-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2015-10-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#1e6823\" data-count=\"35\" data-date=\"2015-10-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-10-10\"/>\n" + " </g>\n" + " <g transform=\"translate(312, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-10-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-10-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-10-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-10-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-10-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-10-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-10-17\"/>\n" + " </g>\n" + " <g transform=\"translate(325, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-10-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2015-10-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2015-10-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-10-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#1e6823\" data-count=\"42\" data-date=\"2015-10-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-10-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-10-24\"/>\n" + " </g>\n" + " <g transform=\"translate(338, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-10-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-10-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-10-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-10-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-10-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-10-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-10-31\"/>\n" + " </g>\n" + " <g transform=\"translate(351, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2015-11-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-11-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-07\"/>\n" + " </g>\n" + " <g transform=\"translate(364, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-11-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-11-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-11-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2015-11-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-11-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2015-11-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2015-11-14\"/>\n" + " </g>\n" + " <g transform=\"translate(377, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-11-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"20\" data-date=\"2015-11-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-11-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-11-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2015-11-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2015-11-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-21\"/>\n" + " </g>\n" + " <g transform=\"translate(390, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2015-11-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2015-11-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-11-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-11-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-11-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2015-11-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-11-28\"/>\n" + " </g>\n" + " <g transform=\"translate(403, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-11-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-12-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#44a340\" data-count=\"27\" data-date=\"2015-12-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-12-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2015-12-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-12-05\"/>\n" + " </g>\n" + " <g transform=\"translate(416, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-12-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2015-12-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2015-12-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#44a340\" data-count=\"26\" data-date=\"2015-12-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2015-12-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-12-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-12-12\"/>\n" + " </g>\n" + " <g transform=\"translate(429, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2015-12-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-12-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2015-12-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-12-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"15\" data-date=\"2015-12-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-12-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2015-12-19\"/>\n" + " </g>\n" + " <g transform=\"translate(442, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2015-12-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#44a340\" data-count=\"27\" data-date=\"2015-12-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"28\" data-date=\"2015-12-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2015-12-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2015-12-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2015-12-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2015-12-26\"/>\n" + " </g>\n" + " <g transform=\"translate(455, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#44a340\" data-count=\"25\" data-date=\"2015-12-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#44a340\" data-count=\"23\" data-date=\"2015-12-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"28\" data-date=\"2015-12-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"17\" data-date=\"2015-12-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2015-12-31\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-01-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#44a340\" data-count=\"32\" data-date=\"2016-01-02\"/>\n" + " </g>\n" + " <g transform=\"translate(468, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2016-01-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#44a340\" data-count=\"26\" data-date=\"2016-01-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"25\" data-date=\"2016-01-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2016-01-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2016-01-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-01-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2016-01-09\"/>\n" + " </g>\n" + " <g transform=\"translate(481, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-01-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-01-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-01-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-01-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-01-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2016-01-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-01-16\"/>\n" + " </g>\n" + " <g transform=\"translate(494, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2016-01-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2016-01-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-01-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2016-01-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2016-01-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-01-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2016-01-23\"/>\n" + " </g>\n" + " <g transform=\"translate(507, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-01-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"19\" data-date=\"2016-01-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"24\" data-date=\"2016-01-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"21\" data-date=\"2016-01-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"16\" data-date=\"2016-01-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2016-01-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2016-01-30\"/>\n" + " </g>\n" + " <g transform=\"translate(520, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-01-31\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-02-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-02-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"15\" data-date=\"2016-02-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#44a340\" data-count=\"32\" data-date=\"2016-02-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2016-02-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-02-06\"/>\n" + " </g>\n" + " <g transform=\"translate(533, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2016-02-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2016-02-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"27\" data-date=\"2016-02-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-02-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#1e6823\" data-count=\"33\" data-date=\"2016-02-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#1e6823\" data-count=\"46\" data-date=\"2016-02-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-02-13\"/>\n" + " </g>\n" + " <g transform=\"translate(546, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-02-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2016-02-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"25\" data-date=\"2016-02-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-02-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2016-02-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2016-02-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#44a340\" data-count=\"27\" data-date=\"2016-02-20\"/>\n" + " </g>\n" + " <g transform=\"translate(559, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-02-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-02-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-02-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2016-02-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2016-02-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-02-26\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-02-27\"/>\n" + " </g>\n" + " <g transform=\"translate(572, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2016-02-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"17\" data-date=\"2016-02-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#44a340\" data-count=\"29\" data-date=\"2016-03-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-03-02\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2016-03-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-03-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-03-05\"/>\n" + " </g>\n" + " <g transform=\"translate(585, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2016-03-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"19\" data-date=\"2016-03-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2016-03-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"19\" data-date=\"2016-03-09\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2016-03-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2016-03-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-03-12\"/>\n" + " </g>\n" + " <g transform=\"translate(598, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-03-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2016-03-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-03-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2016-03-16\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-03-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-03-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-03-19\"/>\n" + " </g>\n" + " <g transform=\"translate(611, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2016-03-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2016-03-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-03-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-03-23\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-03-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-03-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-03-26\"/>\n" + " </g>\n" + " <g transform=\"translate(624, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"2\" data-date=\"2016-03-27\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-03-28\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-03-29\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#8cc665\" data-count=\"18\" data-date=\"2016-03-30\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2016-03-31\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-04-01\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"7\" data-date=\"2016-04-02\"/>\n" + " </g>\n" + " <g transform=\"translate(637, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2016-04-03\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"13\" data-date=\"2016-04-04\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-04-05\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-04-06\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-04-07\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"5\" data-date=\"2016-04-08\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-04-09\"/>\n" + " </g>\n" + " <g transform=\"translate(650, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"9\" data-date=\"2016-04-10\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-04-11\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-04-12\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"10\" data-date=\"2016-04-13\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"19\" data-date=\"2016-04-14\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-04-15\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#d6e685\" data-count=\"1\" data-date=\"2016-04-16\"/>\n" + " </g>\n" + " <g transform=\"translate(663, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#eeeeee\" data-count=\"0\" data-date=\"2016-04-17\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#d6e685\" data-count=\"3\" data-date=\"2016-04-18\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"4\" data-date=\"2016-04-19\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"39\" fill=\"#d6e685\" data-count=\"8\" data-date=\"2016-04-20\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"52\" fill=\"#8cc665\" data-count=\"11\" data-date=\"2016-04-21\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"65\" fill=\"#8cc665\" data-count=\"12\" data-date=\"2016-04-22\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"78\" fill=\"#44a340\" data-count=\"29\" data-date=\"2016-04-23\"/>\n" + " </g>\n" + " <g transform=\"translate(676, 0)\">\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"0\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-04-24\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"13\" fill=\"#8cc665\" data-count=\"14\" data-date=\"2016-04-25\"/>\n" + " <rect class=\"day\" width=\"11\" height=\"11\" y=\"26\" fill=\"#d6e685\" data-count=\"6\" data-date=\"2016-04-26\"/>\n" + " </g>\n" + " <text x=\"13\" y=\"-5\" class=\"month\">May</text>\n" + " <text x=\"78\" y=\"-5\" class=\"month\">Jun</text>\n" + " <text x=\"130\" y=\"-5\" class=\"month\">Jul</text>\n" + " <text x=\"182\" y=\"-5\" class=\"month\">Aug</text>\n" + " <text x=\"247\" y=\"-5\" class=\"month\">Sep</text>\n" + " <text x=\"299\" y=\"-5\" class=\"month\">Oct</text>\n" + " <text x=\"351\" y=\"-5\" class=\"month\">Nov</text>\n" + " <text x=\"416\" y=\"-5\" class=\"month\">Dec</text>\n" + " <text x=\"468\" y=\"-5\" class=\"month\">Jan</text>\n" + " <text x=\"533\" y=\"-5\" class=\"month\">Feb</text>\n" + " <text x=\"585\" y=\"-5\" class=\"month\">Mar</text>\n" + " <text x=\"637\" y=\"-5\" class=\"month\">Apr</text>\n" + " <text text-anchor=\"middle\" class=\"wday\" dx=\"-10\" dy=\"9\" style=\"display: none;\">S</text>\n" + " <text text-anchor=\"middle\" class=\"wday\" dx=\"-10\" dy=\"22\">M</text>\n" + " <text text-anchor=\"middle\" class=\"wday\" dx=\"-10\" dy=\"35\" style=\"display: none;\">T</text>\n" + " <text text-anchor=\"middle\" class=\"wday\" dx=\"-10\" dy=\"48\">W</text>\n" + " <text text-anchor=\"middle\" class=\"wday\" dx=\"-10\" dy=\"61\" style=\"display: none;\">T</text>\n" + " <text text-anchor=\"middle\" class=\"wday\" dx=\"-10\" dy=\"74\">F</text>\n" + " <text text-anchor=\"middle\" class=\"wday\" dx=\"-10\" dy=\"87\" style=\"display: none;\">S</text>\n" + " </g>\n" + "</svg>\n"; private static Util ourInstance = new Util(); public static Util getInstance() { return ourInstance; } private Util() { } }