text:
static Window *s_main_window;
static Layer *s_circle_layer, *s_inside_text_layer, *s_upper_text_layer, *s_lower_text_layer;
static AppTimer *s_animation_completed_timer, *animationTimer, *s_hide_lower_text_layer, *s_click_provider_timer, *s_interrupt_timer, *s_update_hr_timer, *s_main_timer;
static GRect bounds;
static uint8_t s_radius_final, s_radius = 0;
static int s_min_to_breathe = 1, s_min_breathed_today = 0, s_times_played = 0, s_breath_duration, s_breaths_per_minute, s_current_radius;
static bool s_animation_completed = false, s_animating = false, s_main_done;
static GPoint s_center;
static char s_min_to_breathe_text[3] = "1", s_instruct_text[27], s_min_text[25], s_min_today[25], s_greet_text[27], s_start_time[11], s_end_time[11];
static time_t t;
static time_t s_start_stamp;

// ******************************************************************************************* Layer Update Procedures
// Updates circle
static void canvas_update_proc(Layer *s_drawing_layer, GContext *ctx) {
	graphics_draw_main_circle(ctx, settings_get_circleColor(), s_center, s_radius);
}

// Updates text inside circle, side semicircle, and triangles
static void inside_text_layer_update_proc(Layer *s_inside_text_layer, GContext *ctx) {
	graphics_draw_inner_text(ctx, bounds, s_animating, s_min_to_breathe, settings_get_textColor(), s_min_to_breathe_text, s_instruct_text, s_min_text);
}

// Draws text at top of screen
static void upper_text_layer_update_proc(Layer *s_inside_text_layer, GContext *ctx) {
	graphics_draw_upper_text(ctx, bounds, s_animating, settings_get_displayText(), settings_get_textColor(), s_greet_text);
}

// Draws text at bottom of screen
static void lower_text_layer_update_proc(Layer *s_inside_text_layer, GContext *ctx) {
	graphics_draw_lower_text(ctx, bounds, s_animating, settings_get_textColor(), s_min_today);
}

// ******************************************************************************************* Animation Stuff
// Create generic animation
static void create_animation(int duration, int delay, AnimationCurve animationcurve, AnimationImplementation *implementation) {
	// Creates animation instance
	Animation *anim = animation_create();
	animation_set_duration(anim, duration);
	animation_set_delay(anim, delay);
	animation_set_curve(anim, animationcurve);
	animation_set_implementation(anim, implementation);
	// Schedules animation to start
	animation_schedule(anim);
}

// Fires at the end of app start
static void finish_setup_callback(void *context) {
	// Sets string depending on watch language
	snprintf(s_instruct_text, sizeof(s_instruct_text), "%s", localize_get_breathe_text());

	// Animation is completed
	s_animation_completed = true;

	// Draw triangles
	graphics_create_triangles_gpath();

	// Creates more layers to hold text
	s_inside_text_layer = layer_create(bounds);
	layer_set_update_proc(s_inside_text_layer, inside_text_layer_update_proc);

	s_upper_text_layer = layer_create(bounds);
	layer_set_update_proc(s_upper_text_layer, upper_text_layer_update_proc);

	s_lower_text_layer = layer_create(bounds);
	layer_set_update_proc(s_lower_text_layer, lower_text_layer_update_proc);

	// Adds layers to the window
	layer_add_child(window_get_root_layer(s_main_window), s_inside_text_layer);
	layer_add_child(window_get_root_layer(s_main_window), s_upper_text_layer);
	layer_add_child(window_get_root_layer(s_main_window), s_lower_text_layer);
	layer_mark_dirty(s_inside_text_layer);
	layer_mark_dirty(s_upper_text_layer);
	layer_mark_dirty(s_lower_text_layer);
}

// ******************************************************************************************* Other stuff
// Changes text in circle if singular or plural
static void set_min_text(int minutes, void *string) {
	if (minutes == 1) {
			snprintf(string, 5, "%s", "MIN");
		} else {
			snprintf(string, 5, "%s", "MINS");
		}
}

// ******************************************************************************************* Animation Sequence Creator
// Animation while breathing
static void radius_contract_update(Animation *anim, AnimationProgress dist_normalized) {
	s_radius = s_radius_final - dist_normalized * s_radius_final / ANIMATION_NORMALIZED_MAX;
	layer_mark_dirty(s_circle_layer);
}

// Animation while breathing
static void radius_expand_update(Animation *anim, AnimationProgress dist_normalized) {
	s_radius = dist_normalized * s_radius_final / ANIMATION_NORMALIZED_MAX;
	layer_mark_dirty(s_circle_layer);
}

static void interrupt_expand_update(Animation *anim, AnimationProgress dist_normalized) {
	s_radius = s_current_radius + (s_radius_final - s_current_radius) * dist_normalized / ANIMATION_NORMALIZED_MAX; // Adds to current radius
	layer_mark_dirty(s_circle_layer);
}

// Start up animation
static void circle_animation_setup() {
	// Set the update method for animation to radius_update
	static AnimationImplementation s_circle_impl = {
		.update = radius_expand_update
	};
	// Starts animation: duration 1500, delay 250, curve, implementation
	create_animation(D_CIRCLE_ANIMATION_DURATION, D_CIRCLE_ANIMATION_DELAY, AnimationCurveEaseInOut, &s_circle_impl);
}

// First in animation after pressing select button
static void main_animation_start() {
	static AnimationImplementation s_main_animation_start = {
		.update = radius_contract_update
	};
	// Starts animation: duration 2000, delay 0, curve, implementation
	create_animation(D_START_ANIMATION_DURATION, D_START_ANIMATION_DELAY, AnimationCurveEaseInOut, &s_main_animation_start);
}

// Hides lower text
static void hide_lower_text_callback() {
	layer_set_hidden(s_lower_text_layer, true);
}

// End animation show text
static void animation_end_callback(void *data) {
	s_breaths_per_minute = settings_get_breathsPerMinute(); // In case the user changed settings while the they were breathing
	s_breath_duration = settings_get_breathDuration();
	s_animation_completed = true;
	s_animating = false;

	snprintf(s_greet_text, sizeof(s_greet_text), "%s", localize_get_greet_text());

	// If the user breathes during passage from one day to another (i.e. 12AM) then set number of breaths to 0
	snprintf(s_end_time, sizeof(s_end_time), data_get_date_today());

	int complete = (int)data; // This tells us whether the user interrupted their session by pressing back

	if (strcmp(s_start_time, s_end_time) == 0 && complete == 0) { // The date is the same and the user did not interrupt their session
		// Add number of minutes breathed
		s_min_breathed_today += s_min_to_breathe;
	} else if (complete == 1) { // The user interrupted their session, so only add what was breathed before aborting
		s_min_breathed_today += floor((time(NULL) - s_start_stamp) / 60);
	} else { // Not on the same day, so set number to zero
		s_min_breathed_today = 0;
	}

	// Display minutes breathed today
	snprintf(s_min_today, sizeof(s_min_today), localize_get_min_breathed_today_text(), s_min_breathed_today);

	// Persist the number of minutes breathed in total today
	data_write_breathe_persist_data(s_min_breathed_today);
	data_write_date_persist_data();

	if (complete != 1) {
		// Persist the duration of minutes if user didn't interrupt their session
		data_write_last_duration_data(s_min_to_breathe);
	}

	// Sets different number of digits for one digit or two digits
	if (s_min_to_breathe == 10) {
			snprintf(s_min_to_breathe_text, 3, "%d", s_min_to_breathe);
	} else {
		snprintf(s_min_to_breathe_text, 2, "%d", s_min_to_breathe);
	}

	// Shows all the layers because breathing is done
	#ifdef PBL_ROUND
		set_min_text(s_min_to_breathe, s_min_text);
		snprintf(s_instruct_text, sizeof(s_instruct_text), localize_get_breathe_text());
	#endif
	layer_set_hidden(s_inside_text_layer, false);
	layer_set_hidden(s_upper_text_layer, false);
	layer_set_hidden(s_lower_text_layer, false);

	#if defined(PBL_HEALTH)
	// Restore the HR sample period
	if (settings_get_heartRateVariation()) {
		data_set_heart_rate_period(0);
	}
	#endif
}

// Last out animation
static void main_animation_end(void *data) {

	int animation_delay; // No delay
	int animation_duration;
	AnimationCurve animation_curve;
	static AnimationImplementation s_main_animation_end = {
			.update = radius_expand_update
	};

	int complete = (int)data; // Coerce data into int

	if (complete == 0) {
		// Sets duration of animation
		animation_duration = D_END_ANIMATION_DURATION;
		animation_delay = D_END_ANIMATION_DELAY;
		animation_curve = AnimationCurveEaseInOut;

		if (settings_get_vibrationEnabled()) {
			// Vibration to signal that the thing is ended
			vibes_double_pulse();
		}

		// Localized strings
		snprintf(s_min_today, sizeof(s_min_today), localize_get_well_done_text());

		// Show the "Well done text" and then hides it after 2 seconds
		layer_set_hidden(s_lower_text_layer, false);
		s_hide_lower_text_layer = app_timer_register(animation_duration, hide_lower_text_callback, NULL);

		// Next call animation_end_callback to get back to the main menu.
		s_main_timer = app_timer_register(animation_duration+animation_delay, animation_end_callback, NULL);
	} else {
		s_main_animation_end.update = interrupt_expand_update; // Changes the update procedure
		animation_delay = 0;
		animation_duration = 500; // Makes the duration longer
		animation_curve = AnimationCurveEaseOut; // Feels faster than other curves
		layer_set_hidden(s_lower_text_layer, true); // Hides any visible text layers
		layer_set_hidden(s_upper_text_layer, true);
	}

	create_animation(animation_duration, animation_delay, animation_curve, &s_main_animation_end);
}

// Sets up and schedules circle contract and expand
static void main_animation() {
		// Hides text layers
		#ifdef PBL_ROUND
			layer_set_hidden(s_inside_text_layer, true);
		#endif

		// Circle expands for 3 seconds and delays for 1 second
		Animation *circle_expand = animation_create();
		animation_set_duration(circle_expand, s_breath_duration);
		animation_set_curve(circle_expand, AnimationCurveEaseInOut);
		animation_set_delay(circle_expand, D_BREATH_HOLD_TIME);
		static AnimationImplementation s_expand_impl = {
			.update = radius_expand_update
		};
		animation_set_implementation(circle_expand, &s_expand_impl);

		// Circle contracts for 3 seconds and delays for 1 second
		Animation *circle_contract = animation_create();
		animation_set_duration(circle_contract, s_breath_duration);
		animation_set_delay(circle_contract, D_BREATH_HOLD_TIME);
		animation_set_curve(circle_contract, AnimationCurveEaseInOut);
		static AnimationImplementation s_contract_impl = {
			.update = radius_contract_update
		};
		animation_set_implementation(circle_contract, &s_contract_impl);

		// Plays expand and contract as a sequence (delay for 1 second, expand for 3, delay for 1, contract for 3)
		Animation *circle_animation_sequence = animation_sequence_create(circle_expand, circle_contract, NULL);
		animation_schedule(circle_animation_sequence);
		s_times_played++; // Used to keep track to see how many should be played to fill time

		if (settings_get_vibrationEnabled()) {
			int segment_length = 0; // Because it is impossible to find the length of a dynamically allocated array
			switch(settings_get_vibrationType()) {
				case 0: ; // This is vibrations only on inhale
					// Vibrations! (play for 0, rest for 1500, play for 25, rest for 25, etc.)
					static uint32_t *segments;
					switch(s_breaths_per_minute) {
						case 4: ; // 15000 milliseconds long, with an empty statement after a label before a declaration
							static const uint32_t four_segments[49] = {0, 2500, 25, 50, 25, 50, 25, 65, 25, 65, 25, 75, 25, 75, 25, 80, 25, 80, 25, 100, 25, 100, 25, 150, 25, 150, 25, 175, 25, 175, 25, 225, 25, 225, 25, 275, 25, 275, 25, 375, 25, 375, 25, 450, 25, 450, 25, 500, 25};
							segment_length = ARRAY_LENGTH(four_segments); // Get size of array
							segments = (uint32_t *) calloc(segment_length, sizeof(uint32_t)); // Allocate memory equal to size of array to segments and return pointer to segments array
							memcpy(segments, four_segments, sizeof(four_segments)); // Copy each value of array into segments array
							break;
						case 5: ; // 12000 milliseconds long
							static const uint32_t five_segments[44] = {0, 2000, 25, 50, 25, 50, 25, 65, 25, 65, 25, 75, 25, 75, 25, 80, 25, 80, 25, 100, 25, 100, 25, 150, 25, 150, 25, 175, 25, 175, 25, 225, 25, 225, 25, 275, 25, 275, 25, 375, 25, 375, 25};
							segment_length = ARRAY_LENGTH(four_segments);
							segments = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments, five_segments, sizeof(five_segments));
							break;
						case 6:
						case 7: ; // 8000 milliseconds long
							static const uint32_t seven_segments[29] = {0, 1500, 25, 25, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 125, 25, 125, 25, 125, 25, 125, 25, 200, 25, 325, 25, 550, 25};
							segment_length = ARRAY_LENGTH(four_segments);
							segments = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments, seven_segments, sizeof(seven_segments));
							break;
						case 8: // 7000 milliseconds long
						case 9: ;
							static const uint32_t nine_segments[27] = {0, 1500, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 125, 25, 150, 25, 200, 25, 250, 25, 300, 25, 350, 25};
							segment_length = ARRAY_LENGTH(four_segments);
							segments = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments, nine_segments, sizeof(nine_segments));
							break;
						default: ; // 6000 milliseconds long
							static const uint32_t ten_segments[29] = {0, 1100, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 100, 25, 125, 25, 125, 25, 150, 25, 250, 25, 275, 25, 300, 25};
							segment_length = ARRAY_LENGTH(four_segments);
							segments = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments, ten_segments, sizeof(ten_segments));
							break;
					}
					VibePattern vibes = {
						.durations = segments,
						.num_segments = segment_length
					};
					vibes_enqueue_custom_pattern(vibes);
					free(segments);
					break;
				case 1: ; // This is vibrations on inhale and exhale
					static uint32_t *segments_both;
					switch(s_breaths_per_minute) {
						case 4: ; // 15000 milliseconds long, with an empty statement after a label before a declaration
							static const uint32_t four_segments[96] = {0, 2500, 25, 50, 25, 50, 25, 65, 25, 65, 25, 75, 25, 75, 25, 80, 25, 80, 25, 100, 25, 100, 25, 150, 25, 150, 25, 175, 25, 175, 25, 225, 25, 225, 25, 275, 25, 275, 25, 375, 25, 450, 25, 450, 25, 500, 25, 2500, 25, 50, 25, 50, 25, 65, 25, 65, 25, 75, 25, 75, 25, 80, 25, 80, 25, 100, 25, 100, 25, 150, 25, 150, 25, 175, 25, 175, 25, 225, 25, 225, 25, 275, 25, 275, 25, 375, 25, 375, 25, 450, 25, 450, 25, 500, 25};
							segment_length = ARRAY_LENGTH(four_segments);
							segments_both = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments_both, four_segments, sizeof(four_segments));
							break;
						case 5: ; // 12000 milliseconds long
							static const uint32_t five_segments[86] = {0, 2000, 25, 50, 25, 50, 25, 65, 25, 65, 25, 75, 25, 75, 25, 80, 25, 80, 25, 100, 25, 100, 25, 150, 25, 150, 25, 175, 25, 175, 25, 225, 25, 225, 25, 275, 25, 275, 25, 375, 25, 375, 25, 2200, 25, 50, 25, 50, 25, 65, 25, 65, 25, 75, 25, 75, 25, 80, 25, 80, 25, 100, 25, 100, 25, 150, 25, 150, 25, 175, 25, 175, 25, 225, 25, 225, 25, 275, 25, 275, 25, 275, 25};
							segment_length = ARRAY_LENGTH(five_segments);
							segments_both = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments_both, five_segments, sizeof(five_segments));
							break;
						case 6: ; // 8000 milliseconds long
							static const uint32_t six_segments[60] = {0, 1500, 25, 25, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 125, 25, 125, 25, 125, 25, 125, 25, 200, 25, 325, 25, 550, 25, 2600, 25, 25, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 125, 25, 125, 25, 125, 25, 125, 25, 200, 25, 325, 25, 550, 25};
							segment_length = ARRAY_LENGTH(six_segments);
							segments_both = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments_both, six_segments, sizeof(six_segments));
							break;
						case 7: ; // 8000 milliseconds long
							static const uint32_t seven_segments[58] = {0, 1500, 25, 25, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 125, 25, 125, 25, 125, 25, 125, 25, 200, 25, 325, 25, 550, 25, 1800, 25, 25, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 125, 25, 125, 25, 125, 25, 125, 25, 200, 25, 325, 25, 550, 25};
							segment_length = ARRAY_LENGTH(seven_segments);
							segments_both = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments_both, seven_segments, sizeof(seven_segments));
							break;
						case 8: ; // 7000 milliseconds long
							static const uint32_t eight_segments[54] = {0, 1500, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 125, 25, 150, 25, 200, 25, 250, 25, 300, 25, 350, 25, 1700, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 125, 25, 150, 25, 200, 25, 250, 25, 300, 25};
							segment_length = ARRAY_LENGTH(eight_segments);
							segments_both = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments_both, eight_segments, sizeof(eight_segments));
							break;
						case 9: ;
							static const uint32_t nine_segments[54] = {0, 1500, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 125, 25, 150, 25, 200, 25, 250, 25, 300, 25, 350, 25, 1200, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 125, 25, 150, 25, 200, 25, 250, 25, 300, 25};
							segment_length = ARRAY_LENGTH(nine_segments);
							segments_both = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments_both, nine_segments, sizeof(nine_segments));
							break;
						default: ; // 6000 milliseconds long
							static const uint32_t ten_segments[58] = {0, 1000, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 100, 25, 125, 25, 125, 25, 150, 25, 250, 25, 275, 25, 300, 25, 1050, 25, 25, 25, 25, 25, 25, 25, 50, 25, 75, 25, 100, 25, 100, 25, 125, 25, 125, 25, 150, 25, 250, 25, 275, 25};
							segment_length = ARRAY_LENGTH(ten_segments);
							segments_both = (uint32_t *) calloc(segment_length, sizeof(uint32_t));
							memcpy(segments_both, ten_segments, sizeof(ten_segments));
							break;
					}
					VibePattern vibes_both = {
						.durations = segments_both,
						.num_segments = segment_length,
					};
					vibes_enqueue_custom_pattern(vibes_both);
					free(segments_both);
					break;
				default: ; // This is simple vibrations (double tap)
					int vib_on, vib_off; // Declare variables for length of vibration on and rest time between vibrations
					vib_on = 40 + s_breath_duration / 1000;
					vib_off = s_breath_duration / 10 * 2;
					const uint32_t segments_simple[] = {0, 1000, vib_on, vib_off, vib_on, s_breath_duration + 1000 - (vib_off + vib_on * 2), vib_on, vib_off, vib_on};
					VibePattern vibes_simple = {
						.durations = segments_simple,
						.num_segments = ARRAY_LENGTH(segments_simple),
					};
					vibes_enqueue_custom_pattern(vibes_simple);
					break;
			}
		}
}

// Schedules next animation if the number of times played is less than 7 times the number of minutes (seven breaths per minute)
static void main_animation_callback () {

	#if defined(PBL_HEALTH)
	// Update the breathDuration if in variable HR mode, but only if it's higher. (Which means that the breaths are slowing down and people are relaxing! Wow!)
	if (settings_get_heartRateVariation() && data_get_current_heart_rate() != 0) {
		int new_duration = settings_get_breathDuration();
		if (new_duration > s_breath_duration) {
			APP_LOG(APP_LOG_LEVEL_DEBUG, "Old duration %d, new %d", s_breath_duration, new_duration);
			s_breath_duration = new_duration;
			s_breaths_per_minute = settings_get_breathsPerMinute();
		}
	} else {
		s_breath_duration = settings_get_breathDuration(); // Check for changes in the breath duration; it may have been changed in the settings
		s_breaths_per_minute = settings_get_breathsPerMinute();
	}
	#else
		s_breath_duration = settings_get_breathDuration(); // Check for changes in the breath duration; it may have been changed in the settings
		s_breaths_per_minute = settings_get_breathsPerMinute();
	#endif

	// If we are animating and main timer isn't done yet
	if (s_animating && !s_main_done) {
		animationTimer = app_timer_register(2 * s_breath_duration + 2 * D_BREATH_HOLD_TIME, main_animation_callback, NULL); // Run this method again to schedule the next breath
		if (!layer_get_hidden(s_upper_text_layer) || !layer_get_hidden(s_lower_text_layer)) { // The text layers aren't hidden; this keep if HRV is enabled
			if (settings_get_heartRateVariation() && s_times_played > 1) {
				layer_set_hidden(s_upper_text_layer, false); // For the HR text
			} else {
				layer_set_hidden(s_upper_text_layer, true); // HRV isn't enabled, so hide the text layers
				layer_set_hidden(s_lower_text_layer, true);
			}
		}
		main_animation();
	} else { // This means that the main animation is complete
		APP_LOG(APP_LOG_LEVEL_DEBUG, "The animation has stopped.");
		animationTimer = app_timer_register(500, main_animation_end, (void*)0);
	}
}

// Called when main timer is done
static void main_done_callback(void *context) {
	s_main_done = true;
}

#if defined(PBL_HEALTH)
// Update HeartRate in the top slot during a session
static void heart_rate_update_callback(void *context) {
	if (s_animating) {
		data_update_heart_rate_buffer(); // Update heart rate
		snprintf(s_greet_text, sizeof(s_greet_text), data_get_current_heart_rate_buffer()); // Show heart rate upon redraw of s_upper_text_layer
		layer_set_hidden(s_upper_text_layer, false);

		// Re-schedule the timer
		s_update_hr_timer = app_timer_register(s_breath_duration, heart_rate_update_callback, NULL);
	}
}
#endif

// Shows instructions to exhale; first hides the top text and then shows the bottom text
static void first_breath_out_callback(void *context) {

	// Intro done, start timer for when to stop breathing session
	s_main_timer = app_timer_register(s_min_to_breathe * MILLISECONDS_PER_MINUTE - 6000 - D_BREATH_HOLD_TIME - s_breath_duration, main_done_callback, NULL);

	snprintf(s_min_today, sizeof(s_min_today), localize_get_exhale_text());
	layer_set_hidden(s_upper_text_layer, true);
	layer_set_hidden(s_lower_text_layer, false);

	#if defined(PBL_HEALTH)
	// Start HR update timer which shows the heart rate in the upper text field after the first breath
	if (settings_get_heartRateVariation()) {
		s_update_hr_timer = app_timer_register(s_breath_duration * 2, heart_rate_update_callback, NULL);
	}
	#endif
}

// Shows instructions to inhale
static void first_breath_in_callback(void *context) {

	// Next Up, first_breath_out_callback
	s_main_timer = app_timer_register(s_breath_duration, first_breath_out_callback, NULL);

	snprintf(s_greet_text, sizeof(s_greet_text), localize_get_inhale_text());
	layer_set_hidden(s_upper_text_layer, false);
	#ifdef PBL_ROUND
		layer_set_hidden(s_inside_text_layer, true);
	#endif
}

// Start animation show text
static void animation_start_callback(void *context) {

	// Next up, first_breath_in_callback
	s_main_timer = app_timer_register(D_START_ANIMATION_TIME, first_breath_in_callback, NULL);

	// Sets strings as English, change if watch is set to another language
	char *strings[9] = {"TAKE A MOMENT;", "BE STILL;", "CLEAR YOUR MIND;", "EMPTY YOUR THOUGHTS;", "BE CALM;", "THINK NOTHING;", "RELAX;", "CHILL FOR A SEC;", "SPACE OUT;"};
	if (strncmp(localize_get_locale(), "fr", 2) == 0) {
		char *french_strings[9] = {"PRENEZ UN MOMENT;", "NE BOUGEZ PAS;", "VIDEZ VOTRE ESPRIT;", "NE PENSEZ À RIEN;", "SOYEZ CALME;", "CONCENTREZ;", "RELAXEZ;", "NE VOUS INQUIETEZ PAS;", "DONNEZ-VOUS DE L'ESPACE;"};
		for (int i = 0; i <= 8; i++) {
			strings[i] = french_strings[i];
		}
	} else if (strncmp(localize_get_locale(), "es", 2) == 0) {
		char *spanish_strings[9] = {"TOMA UN DESCANSO;", "NO TE MUEVAS;", "ACLARA TU MENTE;", "NO PIENSA A NADA;", "SÉ CALMO;", "CONCÉNTRATE;", "RELÁJATE;", "NO TE PREOCUPES;", "TOMA UN RATO;"};
		for (int i = 0; i <= 8; i++) {
			strings[i] = spanish_strings[i];
		}
	} else if (strncmp(localize_get_locale(), "de", 2) == 0) {
		char *german_strings[9] = {"NIMM DIR ZEIT;", "STEHE STILL;", "LEERE DEINEN GEIST;", "DENKE AN NICHTS;", "WERDE RUHIG;", "EXISTIERE EINFACH;", "MACH'S DIR GEMÜTLICH;", "SPÜRE DEINE UMGEBUNG;", "KOMM RUNTER;"};
		for (int i = 0; i <= 8; i++) {
			strings[i] = german_strings[i];
		}
	}

	// Generates a random number between 0 and 8 and sets string to that index of the array of strings
	int random_number = rand() % 9;
	APP_LOG(APP_LOG_LEVEL_DEBUG, "The random_number is %d", random_number);
	APP_LOG(APP_LOG_LEVEL_DEBUG, "The string is %s", &*strings[random_number]);

	// Same thing as above but for bottom text
	char* bottom_text[4] = {"BREATHE.", "EXHALE.", "CONCENTRATE.", "FOCUS."};
	if (strncmp(localize_get_locale(), "fr", 2) == 0) {
		char* french_bottom_text[4] = {"RESPIREZ.", "EXHALEZ.", "RESPIREZ.", "EXHALEZ."};
		for (int i = 0; i <= 3; i++) {
			bottom_text[i] = french_bottom_text[i];
		}
	} else if (strncmp(localize_get_locale(), "es", 2) == 0) {
		char* spanish_bottom_text[4] = {"RESPIRA.", "EXHALA.", "RESPIRA.", "EXHALA."};
		for (int i = 0; i <= 3; i++) {
			bottom_text[i] = spanish_bottom_text[i];
		}
	} else if (strncmp(localize_get_locale(), "de", 2) == 0) {
		char* german_bottom_text[4] = {"ATME.", "ATME AUS.", "KONZENTRIER DICH.", "FOKUSSIERE DICH."};
		for (int i = 0; i <= 3; i++) {
			bottom_text[i] = german_bottom_text[i];
		}
	}

	int random_number_2 = rand() % 4;
	APP_LOG(APP_LOG_LEVEL_DEBUG, "The random_number #2 is %d", random_number_2);
	APP_LOG(APP_LOG_LEVEL_DEBUG, "The string is %s", &*bottom_text[random_number_2]);

	#ifdef PBL_RECT
		// Shows the text at top and bottom
		snprintf(s_greet_text, sizeof(s_greet_text), "%s", &*strings[random_number]);
		snprintf(s_min_today, sizeof(s_min_today), "%s", &*bottom_text[random_number_2]);
		layer_set_hidden(s_upper_text_layer, false);
		layer_set_hidden(s_lower_text_layer, false);
	#else
		// Shows the text near the center of the screen
		snprintf(s_instruct_text, sizeof(s_instruct_text), "%s", &*strings[random_number]);
		snprintf(s_min_text, sizeof(s_min_text), "%s", &*bottom_text[random_number_2]);
		layer_set_hidden(s_inside_text_layer, false);
	#endif
}

// ******************************************************************************************* Click Handlers

static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
	// Increments number, displays number.
	if ((s_animation_completed) && (s_min_to_breathe < 10)) {
		s_min_to_breathe += 1;
		set_min_text(s_min_to_breathe, s_min_text);
		if (s_min_to_breathe == 10) {
			snprintf(s_min_to_breathe_text, 3, "%d", s_min_to_breathe);
		} else {
			snprintf(s_min_to_breathe_text, 2, "%d", s_min_to_breathe);
		}
		layer_mark_dirty(s_inside_text_layer);
	}
}

static void down_click_handler(ClickRecognizerRef recognizer, void *context) {
	// Decrements number, displays number.
	if ((s_animation_completed) && (s_min_to_breathe > 1)) {
		s_min_to_breathe -= 1;
		set_min_text(s_min_to_breathe, s_min_text);
		snprintf(s_min_to_breathe_text, 2, "%d", s_min_to_breathe);
		layer_mark_dirty(s_inside_text_layer);
	}
}

static void back_click_handler(ClickRecognizerRef recognizer, void *context) {
	if (s_animating) {
		// Prevents any further animations
		animation_unschedule_all();
		vibes_cancel();

		// Destroys all currently running timers
		if (s_animation_completed_timer != NULL) {
			app_timer_cancel(s_animation_completed_timer);
			s_animation_completed_timer = NULL;
		}
		if (animationTimer != NULL) {
			app_timer_cancel(animationTimer);
			animationTimer = NULL;
		}
		if (s_update_hr_timer != NULL) {
			app_timer_cancel(s_update_hr_timer);
			s_update_hr_timer = NULL;
		}
		if (s_main_timer != NULL) {
			app_timer_cancel(s_main_timer);
			s_main_timer = NULL;
		}

		// Shows the expand animation
		s_current_radius = s_radius;
		main_animation_end((void*)1);
		s_interrupt_timer = app_timer_register(525, animation_end_callback, (void*)1);
		s_animating = false;
		s_main_done = true;
	} else {
		window_stack_pop_all(true);
	}
}

static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
	// Only does things if things are not animating
	if (!s_animating) {
		s_times_played = 0;
		s_breaths_per_minute = settings_get_breathsPerMinute();
		s_breath_duration = settings_get_breathDuration();
		s_animating = true;
		s_animation_completed = false;
		s_main_done = false;

		#if defined(PBL_HEALTH)
		// Kick the HR to high gear (update every one second!)
		if (settings_get_heartRateVariation() && data_get_current_heart_rate() != 0) {
			data_set_heart_rate_period(1);
		}
		#endif

		// Hides all text layers
		layer_set_hidden(s_inside_text_layer, true);
		layer_set_hidden(s_upper_text_layer, true);
		layer_set_hidden(s_lower_text_layer, true);

		// Gets timestamp of start time as the epoch time
		s_start_stamp = time(NULL) + 6;

		// Starts the first circle contraction
		main_animation_start();

		// Starts the main timer
		s_main_timer = app_timer_register(D_START_DELAY, animation_start_callback, NULL);

		// First animationTimer, which will schedule the next time the circle expands or contracts
		animationTimer = app_timer_register(6000, main_animation_callback, NULL);

		// Schedules the last out animation (circle expand) after min * duration of 7 breaths + duration of first circle contraction
		APP_LOG(APP_LOG_LEVEL_DEBUG, "The number of minutes to breath is %d.", s_min_to_breathe);
		APP_LOG(APP_LOG_LEVEL_DEBUG, "The number of breaths per minute is %d.", s_breaths_per_minute);
		APP_LOG(APP_LOG_LEVEL_DEBUG, "The duration per breath is %d.", s_breath_duration);

		// Gets today's date to compare with the end date after breathing is finished
		snprintf(s_start_time, sizeof(s_start_time), data_get_date_today());
	}
}

static void click_config_provider(void *context) {
	ButtonId id_up = BUTTON_ID_UP;  // The Up button
	ButtonId id_down = BUTTON_ID_DOWN; // The Down button
	ButtonId id_select = BUTTON_ID_SELECT; // The Select button
	ButtonId id_back = BUTTON_ID_BACK;
	window_single_click_subscribe(id_up, up_click_handler);
	window_single_click_subscribe(id_down, down_click_handler);
	window_single_click_subscribe(id_back, back_click_handler);
	window_single_click_subscribe(id_select, select_click_handler);
}

// ******************************************************************************************* Main App Functions
static void inbox_received_handler(DictionaryIterator *iter, void *context) {
	// When settings happen, save settings, and refresh screen
	settings_handle_settings();
	settings_save_settings();
	window_set_background_color(s_main_window, settings_get_backgroundColor());
	layer_mark_dirty(s_circle_layer);
	layer_mark_dirty(s_inside_text_layer);
	layer_mark_dirty(s_upper_text_layer);
}

static void main_window_load(Window *window){
	// Sets bounds of drawing layer
	bounds = layer_get_bounds(window_get_root_layer(s_main_window));

	// Creates drawing layer and sets update process
	s_circle_layer = layer_create(bounds);
	layer_set_update_proc(s_circle_layer, canvas_update_proc);

	// Adds drawing layer to the window
	layer_add_child(window_get_root_layer(s_main_window), s_circle_layer);
	layer_mark_dirty(s_circle_layer);

	s_center = grect_center_point(&bounds); // Sets the center of the circle to be the center of the screen
	s_radius_final = bounds.size.w / PBL_IF_RECT_ELSE(2.6, 3.3); // Sets the final radius of the circle
	circle_animation_setup(); // Starts the circle animation
}

// Function for when window is destroyed
static void main_window_unload(Window *window) {
	layer_destroy(s_circle_layer);
	layer_destroy(s_upper_text_layer);
	layer_destroy(s_lower_text_layer);
	layer_destroy(s_inside_text_layer);
	vibes_cancel();
	if (s_times_played != 0) {
		app_timer_cancel(animationTimer);
	}
	window_destroy(s_main_window);
}

// Sets click_providers, see click providers section
static void set_click_config_providers() {
	window_set_click_config_provider(s_main_window, click_config_provider);
}

void breathe_window_push(int min) {
	// Starts random number generator
	srand((unsigned) time(&t));

	// Open AppMessage connection
	app_message_register_inbox_received(inbox_received_handler);
	app_message_open(128, 128);

	// Load settings
	s_min_breathed_today = data_read_breathe_persist_data();

	snprintf(s_min_today, sizeof(s_min_today), localize_get_min_breathed_today_text(), s_min_breathed_today);

	// Create main window and assign to pointer
	s_main_window = window_create();
	window_set_background_color(s_main_window, settings_get_backgroundColor());

	// Set functions to handle window
	window_set_window_handlers(s_main_window, (WindowHandlers) {
		.load = main_window_load,
		.unload = main_window_unload
	});

	s_click_provider_timer = app_timer_register(2000, set_click_config_providers, NULL);

	// Starts timer to show text at end of start animation
	const int delay_ms = 1800;
	s_animation_completed_timer = app_timer_register(delay_ms, finish_setup_callback, NULL);

	s_min_to_breathe = min;
	snprintf(s_min_to_breathe_text, sizeof(s_min_to_breathe_text), "%d", s_min_to_breathe);
	set_min_text(s_min_to_breathe, s_min_text);

	snprintf(s_greet_text, sizeof(s_greet_text), localize_get_greet_text());

	// Show window on the watch, with animated = true
	window_stack_push(s_main_window, true);
}


text:
<?php

global $_MODULE;
$_MODULE = array();
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_6bde6531cb3dc89a517c203d2177315d'] = 'Bloc infos contact';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_e4b4279fc7df686f160eaf46e6129f85'] = 'Ajoute un bloc permettant d\'afficher des informations sur les moyens de contacter la boutique';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_20015706a8cbd457cbb6ea3e7d5dc9b3'] = 'Configuration mise à jour';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_c281f92b77ba329f692077d23636f5c9'] = 'Nom de la société';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_dd7bf230fde8d4836917806aff6a6b27'] = 'Adresse';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_1f8261d17452a959e013666c5df45e07'] = 'Numéro de téléphone';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_ce8ae9da5b7cd6c3df2929543a9af92d'] = 'E-mail';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_b17f3f4dcf653a5776792498a9b44d6a'] = 'Mettre à jour la configuration';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_02d4482d332e1aef3437cd61c9bcc624'] = 'Contactez-nous';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_d0398e90769ea6ed2823a3857bcc19ea'] = 'Tél. : ';
$_MODULE['<{blockcontactinfos}prestashop>blockcontactinfos_6a1e265f92087bb6dd18194833fe946b'] = 'E-mail : ';

redpajama_set_name: RedPajamaGithub


text:
package org.apache.cassandra.db.rows;

import java.io.IOException;

import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.rows.Row.Deletion;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.io.util.FileDataInput;
import org.apache.cassandra.utils.SearchIterator;
import org.apache.cassandra.utils.WrappedException;

/**
 * Serialize/deserialize a single Unfiltered (both on-wire and on-disk).
 *

 *
 * The encoded format for an unfiltered is {@code <flags>(<row>|<marker>)} where:
 *

 *

 *     {@code <flags>} is a byte (or two) whose bits are flags used by the rest
 *     of the serialization. Each flag is defined/explained below as the
 *     "Unfiltered flags" constants. One of those flags is an extension flag,
 *     and if present, indicates the presence of a 2ndbyte that contains more
 *     flags. If the extension is not set, defaults are assumed for the flags
 *     of that 2nd byte.
 *

 *

 *     {@code <row>} is
 *        {@code <clustering><sizes>[<pkliveness>][<deletion>][<columns>]<columns_data>}
 *     where:
 *

 *
{@code <clustering>} is the row clustering as serialized by
 *           {@link org.apache.cassandra.db.Clustering.Serializer} (note that static row are an
 *           exception and don't have this).

 *
{@code <sizes>} are the sizes of the whole unfiltered on disk and
 *           of the previous unfiltered. This is only present for sstables and
 *           is used to efficiently skip rows (both forward and backward).

 *
{@code <pkliveness>} is the row primary key liveness infos, and it
 *           contains the timestamp, ttl and local deletion time of that info,
 *           though some/all of those can be absent based on the flags.

 *
{@code deletion} is the row deletion. It's presence is determined
 *           by the flags and if present, it conists of both the deletion
 *           timestamp and local deletion time.

 *
{@code <columns>} are the columns present in the row  encoded by
 *           {@link org.apache.cassandra.db.Columns.Serializer#serializeSubset}. It is absent if the row
 *           contains all the columns of the {@code SerializationHeader} (which
 *           is then indicated by a flag).

 *
{@code <columns_data>} is the data for each of the column present
 *           in the row. The encoding of each data depends on whether the data
 *           is for a simple or complex column:
 *

 *
Simple columns are simply encoded as one {@code <cell>}

 *
Complex columns are encoded as {@code [<delTime>]<n><cell1>...<celln>}
 *                  where {@code <delTime>} is the deletion for this complex
 *                  column (if flags indicates its presence), {@code <n>} is the
 *                  vint encoded value of n, i.e. {@code <celln>}'s 1-based
 *                  inde and {@code <celli>} are the {@code <cell>} for this
 *                  complex column

 *

 *

 *

 *

 *

 *     {@code <marker>} is {@code <bound><deletion>} where {@code <bound>} is
 *     the marker bound as serialized by {@link org.apache.cassandra.db.ClusteringBoundOrBoundary.Serializer}
 *     and {@code <deletion>} is the marker deletion time.
 *

 *

 *

 * The serialization of a {@code <cell>} is defined by {@link Cell.Serializer}.
 */
public class UnfilteredSerializer
{
    public static final UnfilteredSerializer serializer = new UnfilteredSerializer();

    /*
     * Unfiltered flags constants.
     */
    private final static int END_OF_PARTITION     = 0x01; // Signal the end of the partition. Nothing follows a <flags> field with that flag.
    private final static int IS_MARKER            = 0x02; // Whether the encoded unfiltered is a marker or a row. All following markers applies only to rows.
    private final static int HAS_TIMESTAMP        = 0x04; // Whether the encoded row has a timestamp (i.e. if row.partitionKeyLivenessInfo().hasTimestamp() == true).
    private final static int HAS_TTL              = 0x08; // Whether the encoded row has some expiration info (i.e. if row.partitionKeyLivenessInfo().hasTTL() == true).
    private final static int HAS_DELETION         = 0x10; // Whether the encoded row has some deletion info.
    private final static int HAS_ALL_COLUMNS      = 0x20; // Whether the encoded row has all of the columns from the header present.
    private final static int HAS_COMPLEX_DELETION = 0x40; // Whether the encoded row has some complex deletion for at least one of its columns.
    private final static int EXTENSION_FLAG       = 0x80; // If present, another byte is read containing the "extended flags" above.

    /*
     * Extended flags
     */
    private final static int IS_STATIC               = 0x01; // Whether the encoded row is a static. If there is no extended flag, the row is assumed not static.
    /**
     * A shadowable tombstone cannot replace a previous row deletion otherwise it could resurrect a
     * previously deleted cell not updated by a subsequent update, SEE CASSANDRA-11500
     */
    @Deprecated
    private final static int HAS_SHADOWABLE_DELETION = 0x02; // Whether the row deletion is shadowable. If there is no extended flag (or no row deletion), the deletion is assumed not shadowable.
    // A Scylla-specific flag (not supported by Cassandra) that indicates the presence of a shadowable tombstone.
    private final static int HAS_SCYLLA_SHADOWABLE_DELETION = 0x80;

    public void serialize(Unfiltered unfiltered, SerializationHeader header, DataOutputPlus out, int version)
    throws IOException
    {
        assert !header.isForSSTable();
        serialize(unfiltered, header, out, 0, version);
    }

    public void serialize(Unfiltered unfiltered, SerializationHeader header, DataOutputPlus out, long previousUnfilteredSize, int version)
    throws IOException
    {
        if (unfiltered.kind() == Unfiltered.Kind.RANGE_TOMBSTONE_MARKER)
        {
            serialize((RangeTombstoneMarker) unfiltered, header, out, previousUnfilteredSize, version);
        }
        else
        {
            serialize((Row) unfiltered, header, out, previousUnfilteredSize, version);
        }
    }

    public void serializeStaticRow(Row row, SerializationHeader header, DataOutputPlus out, int version)
    throws IOException
    {
        assert row.isStatic();
        serialize(row, header, out, 0, version);
    }

    private void serialize(Row row, SerializationHeader header, DataOutputPlus out, long previousUnfilteredSize, int version)
    throws IOException
    {
        int flags = 0;
        int extendedFlags = 0;

        boolean isStatic = row.isStatic();
        Columns headerColumns = header.columns(isStatic);
        LivenessInfo pkLiveness = row.primaryKeyLivenessInfo();
        Row.Deletion deletion = row.deletion();
        boolean hasComplexDeletion = row.hasComplexDeletion();
        boolean hasAllColumns = row.columnCount() == headerColumns.size();
        boolean hasExtendedFlags = hasExtendedFlags(row);

        if (isStatic)
            extendedFlags |= IS_STATIC;

        if (!pkLiveness.isEmpty())
            flags |= HAS_TIMESTAMP;
        if (pkLiveness.isExpiring())
            flags |= HAS_TTL;
        if (!deletion.isLive())
        {
            flags |= HAS_DELETION;
            if (deletion.isShadowable())
                extendedFlags |= HAS_SHADOWABLE_DELETION;
        }
        if (hasComplexDeletion)
            flags |= HAS_COMPLEX_DELETION;
        if (hasAllColumns)
            flags |= HAS_ALL_COLUMNS;

        if (hasExtendedFlags)
            flags |= EXTENSION_FLAG;

        out.writeByte((byte)flags);
        if (hasExtendedFlags)
            out.writeByte((byte)extendedFlags);

        if (!isStatic)
            Clustering.serializer.serialize(row.clustering(), out, version, header.clusteringTypes());

        if (header.isForSSTable())
        {
            try (DataOutputBuffer dob = DataOutputBuffer.scratchBuffer.get())
            {
                serializeRowBody(row, flags, header, dob);

                out.writeUnsignedVInt(dob.position() + TypeSizes.sizeofUnsignedVInt(previousUnfilteredSize));
                // We write the size of the previous unfiltered to make reverse queries more efficient (and simpler).
                // This is currently not used however and using it is tbd.
                out.writeUnsignedVInt(previousUnfilteredSize);
                out.write(dob.getData(), 0, dob.getLength());
            }
        }
        else
        {
            serializeRowBody(row, flags, header, out);
        }
    }

    @Inline
    private void serializeRowBody(Row row, int flags, SerializationHeader header, DataOutputPlus out)
    throws IOException
    {
        boolean isStatic = row.isStatic();

        Columns headerColumns = header.columns(isStatic);
        LivenessInfo pkLiveness = row.primaryKeyLivenessInfo();
        Row.Deletion deletion = row.deletion();

        if ((flags & HAS_TIMESTAMP) != 0)
            header.writeTimestamp(pkLiveness.timestamp(), out);
        if ((flags & HAS_TTL) != 0)
        {
            header.writeTTL(pkLiveness.ttl(), out);
            header.writeLocalDeletionTime(pkLiveness.localExpirationTime(), out);
        }
        if ((flags & HAS_DELETION) != 0)
            header.writeDeletionTime(deletion.time(), out);

        if ((flags & HAS_ALL_COLUMNS) == 0)
            Columns.serializer.serializeSubset(row.columns(), headerColumns, out);

        SearchIterator<ColumnDefinition, ColumnDefinition> si = headerColumns.iterator();

        try
        {
            row.apply(cd -> {
                // We can obtain the column for data directly from data.column(). However, if the cell/complex data
                // originates from a sstable, the column we'll get will have the type used when the sstable was serialized,
                // and if that type have been recently altered, that may not be the type we want to serialize the column
                // with. So we use the ColumnDefinition from the "header" which is "current". Also see #11810 for what
                // happens if we don't do that.
                ColumnDefinition column = si.next(cd.column());
                assert column != null;

                try
                {
                    if (cd.column.isSimple())
                        Cell.serializer.serialize((Cell) cd, column, out, pkLiveness, header);
                    else
                        writeComplexColumn((ComplexColumnData) cd, column, (flags & HAS_COMPLEX_DELETION) != 0, pkLiveness, header, out);
                }
                catch (IOException e)
                {
                    throw new WrappedException(e);
                }
            }, false);
        }
        catch (WrappedException e)
        {
            if (e.getCause() instanceof IOException)
                throw (IOException) e.getCause();

            throw e;
        }
    }

    private void writeComplexColumn(ComplexColumnData data, ColumnDefinition column, boolean hasComplexDeletion, LivenessInfo rowLiveness, SerializationHeader header, DataOutputPlus out)
    throws IOException
    {
        if (hasComplexDeletion)
            header.writeDeletionTime(data.complexDeletion(), out);

        out.writeUnsignedVInt(data.cellsCount());
        for (Cell cell : data)
            Cell.serializer.serialize(cell, column, out, rowLiveness, header);
    }

    private void serialize(RangeTombstoneMarker marker, SerializationHeader header, DataOutputPlus out, long previousUnfilteredSize, int version)
    throws IOException
    {
        out.writeByte((byte)IS_MARKER);
        ClusteringBoundOrBoundary.serializer.serialize(marker.clustering(), out, version, header.clusteringTypes());

        if (header.isForSSTable())
        {
            out.writeUnsignedVInt(serializedMarkerBodySize(marker, header, previousUnfilteredSize, version));
            out.writeUnsignedVInt(previousUnfilteredSize);
        }

        if (marker.isBoundary())
        {
            RangeTombstoneBoundaryMarker bm = (RangeTombstoneBoundaryMarker)marker;
            header.writeDeletionTime(bm.endDeletionTime(), out);
            header.writeDeletionTime(bm.startDeletionTime(), out);
        }
        else
        {
            header.writeDeletionTime(((RangeTombstoneBoundMarker)marker).deletionTime(), out);
        }
    }

    public long serializedSize(Unfiltered unfiltered, SerializationHeader header, int version)
    {
        assert !header.isForSSTable();
        return serializedSize(unfiltered, header, 0, version);
    }

    public long serializedSize(Unfiltered unfiltered, SerializationHeader header, long previousUnfilteredSize,int version)
    {
        return unfiltered.kind() == Unfiltered.Kind.RANGE_TOMBSTONE_MARKER
             ? serializedSize((RangeTombstoneMarker) unfiltered, header, previousUnfilteredSize, version)
             : serializedSize((Row) unfiltered, header, previousUnfilteredSize, version);
    }

    private long serializedSize(Row row, SerializationHeader header, long previousUnfilteredSize, int version)
    {
        long size = 1; // flags

        if (hasExtendedFlags(row))
            size += 1; // extended flags

        if (!row.isStatic())
            size += Clustering.serializer.serializedSize(row.clustering(), version, header.clusteringTypes());

        return size + serializedRowBodySize(row, header, previousUnfilteredSize, version);
    }

    private long serializedRowBodySize(Row row, SerializationHeader header, long previousUnfilteredSize, int version)
    {
        long size = 0;

        if (header.isForSSTable())
            size += TypeSizes.sizeofUnsignedVInt(previousUnfilteredSize);

        boolean isStatic = row.isStatic();
        Columns headerColumns = header.columns(isStatic);
        LivenessInfo pkLiveness = row.primaryKeyLivenessInfo();
        Row.Deletion deletion = row.deletion();
        boolean hasComplexDeletion = row.hasComplexDeletion();
        boolean hasAllColumns = row.columnCount() == headerColumns.size();

        if (!pkLiveness.isEmpty())
            size += header.timestampSerializedSize(pkLiveness.timestamp());
        if (pkLiveness.isExpiring())
        {
            size += header.ttlSerializedSize(pkLiveness.ttl());
            size += header.localDeletionTimeSerializedSize(pkLiveness.localExpirationTime());
        }
        if (!deletion.isLive())
            size += header.deletionTimeSerializedSize(deletion.time());

        if (!hasAllColumns)
            size += Columns.serializer.serializedSubsetSize(row.columns(), header.columns(isStatic));

        SearchIterator<ColumnDefinition, ColumnDefinition> si = headerColumns.iterator();
        for (ColumnData data : row)
        {
            ColumnDefinition column = si.next(data.column());
            if (column == null)
                continue;

            if (data.column.isSimple())
                size += Cell.serializer.serializedSize((Cell) data, column, pkLiveness, header);
            else
                size += sizeOfComplexColumn((ComplexColumnData) data, column, hasComplexDeletion, pkLiveness, header);
        }

        return size;
    }

    private long sizeOfComplexColumn(ComplexColumnData data, ColumnDefinition column, boolean hasComplexDeletion, LivenessInfo rowLiveness, SerializationHeader header)
    {
        long size = 0;

        if (hasComplexDeletion)
            size += header.deletionTimeSerializedSize(data.complexDeletion());

        size += TypeSizes.sizeofUnsignedVInt(data.cellsCount());
        for (Cell cell : data)
            size += Cell.serializer.serializedSize(cell, column, rowLiveness, header);

        return size;
    }

    private long serializedSize(RangeTombstoneMarker marker, SerializationHeader header, long previousUnfilteredSize, int version)
    {
        assert !header.isForSSTable();
        return 1 // flags
             + ClusteringBoundOrBoundary.serializer.serializedSize(marker.clustering(), version, header.clusteringTypes())
             + serializedMarkerBodySize(marker, header, previousUnfilteredSize, version);
    }

    private long serializedMarkerBodySize(RangeTombstoneMarker marker, SerializationHeader header, long previousUnfilteredSize, int version)
    {
        long size = 0;
        if (header.isForSSTable())
            size += TypeSizes.sizeofUnsignedVInt(previousUnfilteredSize);

        if (marker.isBoundary())
        {
            RangeTombstoneBoundaryMarker bm = (RangeTombstoneBoundaryMarker)marker;
            size += header.deletionTimeSerializedSize(bm.endDeletionTime());
            size += header.deletionTimeSerializedSize(bm.startDeletionTime());
        }
        else
        {
           size += header.deletionTimeSerializedSize(((RangeTombstoneBoundMarker)marker).deletionTime());
        }
        return size;
    }

    public void writeEndOfPartition(DataOutputPlus out) throws IOException
    {
        out.writeByte((byte)1);
    }

    public long serializedSizeEndOfPartition()
    {
        return 1;
    }

    /**
     * Deserialize an {@link Unfiltered} from the provided input.
     *
     * @param in the input from which to deserialize.
     * @param header serialization header corresponding to the serialized data.
     * @param helper the helper to use for deserialization.
     * @param builder a row builder, passed here so we don't allocate a new one for every new row.
     * @return the deserialized {@link Unfiltered} or {@code null} if we've read the end of a partition. This method is
     * guaranteed to never return empty rows.
     */
    public Unfiltered deserialize(DataInputPlus in, SerializationHeader header, SerializationHelper helper, Row.Builder builder)
    throws IOException
    {
        while (true)
        {
            Unfiltered unfiltered = deserializeOne(in, header, helper, builder);
            if (unfiltered == null)
                return null;

            // Skip empty rows, see deserializeOne javadoc
            if (!unfiltered.isEmpty())
                return unfiltered;
        }
    }

    /**
     * Deserialize a single {@link Unfiltered} from the provided input.
     *

     * WARNING: this can return an empty row because it's possible there is a row serialized, but that row only
     * contains data for dropped columns, see CASSANDRA-13337. But as most code expect rows to not be empty, this isn't
     * meant to be exposed publicly.
     *
     * But as {@link UnfilteredRowIterator} should not return empty
     * rows, this mean consumer of this method should make sure to skip said empty rows.
     */
    private Unfiltered deserializeOne(DataInputPlus in, SerializationHeader header, SerializationHelper helper, Row.Builder builder)
    throws IOException
    {
        // It wouldn't be wrong per-se to use an unsorted builder, but it would be inefficient so make sure we don't do it by mistake
        assert builder.isSorted();

        int flags = in.readUnsignedByte();
        if (isEndOfPartition(flags))
            return null;

        int extendedFlags = readExtendedFlags(in, flags);

        if (kind(flags) == Unfiltered.Kind.RANGE_TOMBSTONE_MARKER)
        {
            ClusteringBoundOrBoundary bound = ClusteringBoundOrBoundary.serializer.deserialize(in, helper.version, header.clusteringTypes());
            return deserializeMarkerBody(in, header, bound);
        }
        else
        {
            // deserializeStaticRow should be used for that.
            if (isStatic(extendedFlags))
                throw new IOException("Corrupt flags value for unfiltered partition (isStatic flag set): " + flags);

            builder.newRow(Clustering.serializer.deserialize(in, helper.version, header.clusteringTypes()));
            return deserializeRowBody(in, header, helper, flags, extendedFlags, builder);
        }
    }

    private static DeletionTime readScyllaShadowableDeletion(DataInputPlus in, SerializationHeader header, int flags) throws IOException {
        return (flags & HAS_SCYLLA_SHADOWABLE_DELETION) != 0 ? header.readDeletionTime(in) : null;
    }

    public Unfiltered deserializeTombstonesOnly(FileDataInput in, SerializationHeader header, SerializationHelper helper)
    throws IOException
    {
        while (true)
        {
            int flags = in.readUnsignedByte();
            if (isEndOfPartition(flags))
                return null;

            int extendedFlags = readExtendedFlags(in, flags);

            if (kind(flags) == Unfiltered.Kind.RANGE_TOMBSTONE_MARKER)
            {
                ClusteringBoundOrBoundary bound = ClusteringBoundOrBoundary.serializer.deserialize(in, helper.version, header.clusteringTypes());
                return deserializeMarkerBody(in, header, bound);
            }
            else
            {
                assert !isStatic(extendedFlags); // deserializeStaticRow should be used for that.
                if ((flags & HAS_DELETION) != 0)
                {
                    assert header.isForSSTable();
                    boolean hasTimestamp = (flags & HAS_TIMESTAMP) != 0;
                    boolean hasTTL = (flags & HAS_TTL) != 0;
                    boolean deletionIsShadowable = (extendedFlags & HAS_SHADOWABLE_DELETION) != 0;
                    Clustering clustering = Clustering.serializer.deserialize(in, helper.version, header.clusteringTypes());
                    long nextPosition = in.readUnsignedVInt() + in.getFilePointer();
                    in.readUnsignedVInt(); // skip previous unfiltered size
                    if (hasTimestamp)
                    {
                        header.readTimestamp(in);
                        if (hasTTL)
                        {
                            header.readTTL(in);
                            header.readLocalDeletionTime(in);
                        }
                    }

                    Deletion deletion = new Row.Deletion(header.readDeletionTime(in),
                                                         deletionIsShadowable,
                                                         readScyllaShadowableDeletion(in, header, extendedFlags));
                    in.seek(nextPosition);
                    return BTreeRow.emptyDeletedRow(clustering, deletion);
                }
                else
                {
                    readScyllaShadowableDeletion(in, header, extendedFlags);
                    Clustering.serializer.skip(in, helper.version, header.clusteringTypes());
                    skipRowBody(in);
                    // Continue with next item.
                }
            }
        }
    }

    public Row deserializeStaticRow(DataInputPlus in, SerializationHeader header, SerializationHelper helper)
    throws IOException
    {
        int flags = in.readUnsignedByte();
        assert !isEndOfPartition(flags) && kind(flags) == Unfiltered.Kind.ROW && isExtended(flags) : flags;
        int extendedFlags = in.readUnsignedByte();
        Row.Builder builder = BTreeRow.sortedBuilder();
        builder.newRow(Clustering.STATIC_CLUSTERING);
        return deserializeRowBody(in, header, helper, flags, extendedFlags, builder);
    }

    public RangeTombstoneMarker deserializeMarkerBody(DataInputPlus in, SerializationHeader header, ClusteringBoundOrBoundary bound)
    throws IOException
    {
        if (header.isForSSTable())
        {
            in.readUnsignedVInt(); // marker size
            in.readUnsignedVInt(); // previous unfiltered size
        }

        if (bound.isBoundary())
            return new RangeTombstoneBoundaryMarker((ClusteringBoundary) bound, header.readDeletionTime(in), header.readDeletionTime(in));
        else
            return new RangeTombstoneBoundMarker((ClusteringBound) bound, header.readDeletionTime(in));
    }

    public Row deserializeRowBody(DataInputPlus in,
                                  SerializationHeader header,
                                  SerializationHelper helper,
                                  int flags,
                                  int extendedFlags,
                                  Row.Builder builder)
    throws IOException
    {
        try
        {
            boolean isStatic = isStatic(extendedFlags);
            boolean hasTimestamp = (flags & HAS_TIMESTAMP) != 0;
            boolean hasTTL = (flags & HAS_TTL) != 0;
            boolean hasDeletion = (flags & HAS_DELETION) != 0;
            boolean deletionIsShadowable = (extendedFlags & HAS_SHADOWABLE_DELETION) != 0;
            boolean hasComplexDeletion = (flags & HAS_COMPLEX_DELETION) != 0;
            boolean hasAllColumns = (flags & HAS_ALL_COLUMNS) != 0;
            Columns headerColumns = header.columns(isStatic);

            if (header.isForSSTable())
            {
                in.readUnsignedVInt(); // Skip row size
                in.readUnsignedVInt(); // previous unfiltered size
            }

            LivenessInfo rowLiveness = LivenessInfo.EMPTY;
            if (hasTimestamp)
            {
                long timestamp = header.readTimestamp(in);
                int ttl = hasTTL ? header.readTTL(in) : LivenessInfo.NO_TTL;
                int localDeletionTime = hasTTL ? header.readLocalDeletionTime(in) : LivenessInfo.NO_EXPIRATION_TIME;
                rowLiveness = LivenessInfo.withExpirationTime(timestamp, ttl, localDeletionTime);
            }

            builder.addPrimaryKeyLivenessInfo(rowLiveness);
            if (hasDeletion) {
                builder.addRowDeletion(new Row.Deletion(header.readDeletionTime(in),
                                                        deletionIsShadowable,
                                                        readScyllaShadowableDeletion(in, header, extendedFlags)));
            } else {
                builder.addRowDeletion(Row.Deletion.live(readScyllaShadowableDeletion(in, header, extendedFlags)));
            }

            Columns columns = hasAllColumns ? headerColumns : Columns.serializer.deserializeSubset(headerColumns, in);

            final LivenessInfo livenessInfo = rowLiveness;

            try
            {
                columns.apply(column -> {
                    try
                    {
                        if (column.isSimple())
                            readSimpleColumn(column, in, header, helper, builder, livenessInfo);
                        else
                            readComplexColumn(column, in, header, helper, hasComplexDeletion, builder, livenessInfo);
                    }
                    catch (IOException e)
                    {
                        throw new WrappedException(e);
                    }
                }, false);
            }
            catch (WrappedException e)
            {
                if (e.getCause() instanceof IOException)
                    throw (IOException) e.getCause();

                throw e;
            }

            return builder.build();
        }
        catch (RuntimeException | AssertionError e)
        {
            // Corrupted data could be such that it triggers an assertion in the row Builder, or break one of its assumption.
            // Of course, a bug in said builder could also trigger this, but it's impossible a priori to always make the distinction
            // between a real bug and data corrupted in just the bad way. Besides, re-throwing as an IOException doesn't hide the
            // exception, it just make we catch it properly and mark the sstable as corrupted.
            throw new IOException("Error building row with data deserialized from " + in, e);
        }
    }

    private void readSimpleColumn(ColumnDefinition column, DataInputPlus in, SerializationHeader header, SerializationHelper helper, Row.Builder builder, LivenessInfo rowLiveness)
    throws IOException
    {
        if (helper.includes(column))
        {
            Cell cell = Cell.serializer.deserialize(in, rowLiveness, column, header, helper);
            if (helper.includes(cell, rowLiveness) && !helper.isDropped(cell, false))
                builder.addCell(cell);
        }
        else
        {
            Cell.serializer.skip(in, column, header);
        }
    }

    private void readComplexColumn(ColumnDefinition column, DataInputPlus in, SerializationHeader header, SerializationHelper helper, boolean hasComplexDeletion, Row.Builder builder, LivenessInfo rowLiveness)
    throws IOException
    {
        if (helper.includes(column))
        {
            helper.startOfComplexColumn(column);
            if (hasComplexDeletion)
            {
                DeletionTime complexDeletion = header.readDeletionTime(in);
                if (!helper.isDroppedComplexDeletion(complexDeletion))
                    builder.addComplexDeletion(column, complexDeletion);
            }

            int count = (int) in.readUnsignedVInt();
            while (--count >= 0)
            {
                Cell cell = Cell.serializer.deserialize(in, rowLiveness, column, header, helper);
                if (helper.includes(cell, rowLiveness) && !helper.isDropped(cell, true))
                    builder.addCell(cell);
            }

            helper.endOfComplexColumn();
        }
        else
        {
            skipComplexColumn(in, column, header, hasComplexDeletion);
        }
    }

    public void skipRowBody(DataInputPlus in) throws IOException
    {
        int rowSize = (int)in.readUnsignedVInt();
        in.skipBytesFully(rowSize);
    }

    public void skipStaticRow(DataInputPlus in, SerializationHeader header, SerializationHelper helper) throws IOException
    {
        int flags = in.readUnsignedByte();
        assert !isEndOfPartition(flags) && kind(flags) == Unfiltered.Kind.ROW && isExtended(flags) : "Flags is " + flags;
        int extendedFlags = in.readUnsignedByte();
        assert isStatic(extendedFlags);
        skipRowBody(in);
    }

    public void skipMarkerBody(DataInputPlus in) throws IOException
    {
        int markerSize = (int)in.readUnsignedVInt();
        in.skipBytesFully(markerSize);
    }

    private void skipComplexColumn(DataInputPlus in, ColumnDefinition column, SerializationHeader header, boolean hasComplexDeletion)
    throws IOException
    {
        if (hasComplexDeletion)
            header.skipDeletionTime(in);

        int count = (int) in.readUnsignedVInt();
        while (--count >= 0)
            Cell.serializer.skip(in, column, header);
    }

    public static boolean isEndOfPartition(int flags)
    {
        return (flags & END_OF_PARTITION) != 0;
    }

    public static Unfiltered.Kind kind(int flags)
    {
        return (flags & IS_MARKER) != 0 ? Unfiltered.Kind.RANGE_TOMBSTONE_MARKER : Unfiltered.Kind.ROW;
    }

    public static boolean isStatic(int extendedFlags)
    {
        return (extendedFlags & IS_STATIC) != 0;
    }

    private static boolean isExtended(int flags)
    {
        return (flags & EXTENSION_FLAG) != 0;
    }

    public static int readExtendedFlags(DataInputPlus in, int flags) throws IOException
    {
        return isExtended(flags) ? in.readUnsignedByte() : 0;
    }

    public static boolean hasExtendedFlags(Row row)
    {
        return row.isStatic() || row.deletion().isShadowable();
    }
}


text:
module GUI.SaveAs (saveAsPDF, saveAsPNG) where

-- Imports for ThreadScope
import GUI.Timeline.Render (renderTraces, renderYScaleArea)
import GUI.Timeline.Render.Constants
import GUI.Timeline.Ticks (renderXScaleArea)
import GUI.Types
import Events.HECs

-- Imports for GTK
import Graphics.UI.Gtk hiding (rectangle)
import Graphics.Rendering.Cairo
  ( Render
  , Operator(..)
  , Format(..)
  , rectangle
  , getOperator
  , setOperator
  , fill
  , translate
  , liftIO
  , withPDFSurface
  , renderWith
  , withImageSurface
  , surfaceWriteToPNG
  )

saveAs :: HECs -> ViewParameters -> Double -> DrawingArea
       -> (Int, Int, Render ())
saveAs hecs params' @ViewParameters{xScaleAreaHeight, width,
                                    height = oldHeight {-, histogramHeight-}}
       yScaleAreaWidth yScaleArea =
  let histTotalHeight = histXScaleHeight -- + histogramHeight
      params@ViewParameters{height} =
        params'{ viewTraces = viewTraces params' -- ++ [TraceHistogram]
               , height = oldHeight + histTotalHeight + tracePad
               }
      w = ceiling yScaleAreaWidth + width
      h = xScaleAreaHeight + height
      drawTraces = renderTraces params hecs (Rectangle 0 0 width height)
      drawXScale = renderXScaleArea params hecs
      drawYScale = renderYScaleArea params hecs yScaleArea
      -- Functions renderTraces and renderXScaleArea draw to the left of 0
      -- which is not seen in the normal mode, but would be seen in export,
      -- so it has to be cleared before renderYScaleArea is written on top:
      clearLeftArea = do
        rectangle 0 0 yScaleAreaWidth (fromIntegral h)
        op <- getOperator
        setOperator OperatorClear
        fill
        setOperator op
      drawAll = do
        translate yScaleAreaWidth (fromIntegral xScaleAreaHeight)
        drawTraces
        translate 0 (- fromIntegral xScaleAreaHeight)
        drawXScale
        translate (-yScaleAreaWidth) 0
        clearLeftArea
        translate 0 (fromIntegral xScaleAreaHeight)
        drawYScale
  in (w, h, drawAll)

saveAsPDF :: FilePath -> HECs -> ViewParameters -> DrawingArea -> IO ()
saveAsPDF filename hecs params yScaleArea = do
  (xoffset, _) <- liftIO $ widgetGetSize yScaleArea
  let (w', h', drawAll) = saveAs hecs params (fromIntegral xoffset) yScaleArea
  withPDFSurface filename (fromIntegral w') (fromIntegral h') $ \surface ->
    renderWith surface drawAll

saveAsPNG :: FilePath -> HECs -> ViewParameters -> DrawingArea -> IO ()
saveAsPNG filename hecs params yScaleArea = do
  (xoffset, _) <- liftIO $ widgetGetSize yScaleArea
  let (w', h', drawAll) = saveAs hecs params (fromIntegral xoffset) yScaleArea
  withImageSurface FormatARGB32 w' h' $ \surface -> do
    renderWith surface drawAll
    surfaceWriteToPNG surface filename


text:
require_relative '../spec_helper'
require_relative './http_authentication_helper'
require 'helpers/unique_names_helper'

describe SignupController do
  include UniqueNamesHelper

  before(:each) do
    ::User.any_instance.stubs(:load_common_data).returns(true)
  end

  describe 'signup page' do
    include_context 'organization with users helper'

    after(:each) do
      @fake_organization.delete if @fake_organization
    end

    it 'returns 200 when subdomainless and route is signup_subdomainless' do
      @fake_organization = create(:organization_whitelist_carto)
      CartoDB.stubs(:subdomainless_urls?).returns(true)
      CartoDB.stubs(:session_domain).returns('localhost.lan')
      Carto::Organization.stubs(:where).returns([@fake_organization])
      host! "localhost.lan"
      get signup_subdomainless_url(user_domain: 'organization')
      response.status.should == 200
    end

    it 'returns 404 when subdomainless and route is signup' do
      @fake_organization = create(:organization_whitelist_carto)
      CartoDB.stubs(:subdomainless_urls?).returns(true)
      CartoDB.stubs(:session_domain).returns('localhost.lan')
      Carto::Organization.stubs(:where).returns([@fake_organization])
      host! "localhost.lan"
      get signup_url
      response.status.should == 404
    end

    it 'returns 404 outside organization subdomains' do
      get signup_url
      response.status.should == 404
      post signup_organization_user_url
      response.status.should == 404
    end

    it 'returns 200 for organizations with signup_page_enabled' do
      @fake_organization = create(:organization_whitelist_carto)
      Carto::Organization.stubs(:where).returns([@fake_organization])
      get signup_url
      response.status.should == 200
    end

    it 'returns 404 for organizations without signup_page_enabled' do
      @fake_organization = create(:organization, whitelisted_email_domains: [])
      Carto::Organization.stubs(:where).returns([@fake_organization])
      get signup_url
      response.status.should == 404
    end

    it 'returns 404 for organizations with whitelisted domains but without any authentication enabled' do
      @fake_organization = create(:organization_whitelist_carto,
                                              auth_username_password_enabled: true,
                                              auth_google_enabled: false,
                                              auth_github_enabled: false)
      @fake_organization.stubs(:auth_username_password_enabled).returns(false)
      Carto::Organization.stubs(:where).returns([@fake_organization])
      get signup_url
      response.status.should == 404
    end

    it 'returns 200 for organizations without signup_page_enabled but with a valid invitation' do
      @fake_organization = create(:organization_with_users, whitelisted_email_domains: [])
      owner = Carto::User.find(@fake_organization.owner.id)
      invitation = Carto::Invitation.create_new(owner, ['wadus@wad.us'], 'Welcome!', false)
      Carto::Organization.stubs(:where).returns([@fake_organization])
      get signup_url(invitation_token: invitation.token('wadus@wad.us'), email: 'wadus@wad.us')
      response.status.should == 200
    end

    it 'returns user error with admin mail if organization has not enough seats' do
      fake_owner = create(:valid_user).carto_user
      @fake_organization = create(:organization_whitelist_carto, seats: 0, owner: fake_owner)
      Carto::Organization.stubs(:where).returns([@fake_organization])

      get signup_url
      response.status.should == 200
      response.body.should include("organization not enough seats")
      response.body.should include("contact the administrator of #{@fake_organization.name}")
    end

    it 'does not return an error if organization has no unassigned_quota left but the invited user is a viewer' do
      email = 'viewer_user@whatever.com'
      @organization.quota_in_bytes = @organization.assigned_quota
      @organization.save
      user = Carto::User.find(@org_user_owner.id)
      invitation = Carto::Invitation.create_new(user, [email], 'W!', true)
      invitation.save
      token = invitation.token(email)

      host! "#{@organization.name}.localhost.lan"
      get signup_organization_user_url(user_domain: @organization.name,
                                       user: { username: 'viewer-user',
                                               email: email,
                                               password: '2{Patrañas}' },
                                               invitation_token: token)

      response.status.should == 200
      response.body.should_not include("quota_in_bytes not enough disk quota")
    end

    it 'returns an error if organization has no unassigned_quota and invited user is not a viewer' do
      email = 'viewer_user@whatever.com'
      @organization.quota_in_bytes = @organization.assigned_quota
      @organization.whitelisted_email_domains = ['whatever.com']
      @organization.save
      user = Carto::User.find(@org_user_owner.id)
      invitation = Carto::Invitation.create_new(user, [email], 'W!', false)
      invitation.save
      token = invitation.token(email)

      host! "#{@organization.name}.localhost.lan"
      get signup_organization_user_url(user_domain: @organization.name,
                                       user: { username: 'viewer-user',
                                               email: email,
                                               password: '2{Patrañas}' },
                                               invitation_token: token)

      response.status.should == 200
      response.body.should include("quota_in_bytes not enough disk quota")
    end

    it 'signs user up as viewer even if all non-viewer seats are taken' do
      @fake_organization = create(:organization_with_users, whitelisted_email_domains: [])
      @fake_organization.seats = @fake_organization.builder_users.count(&:builder?)
      @fake_organization.viewer_seats = 10
      @fake_organization.save
      owner = Carto::User.find(@fake_organization.owner.id)
      invitation = Carto::Invitation.create_new(owner, ['wadus@wad.us'], 'Welcome!', true)
      host! "#{@fake_organization.name}.localhost.lan"
      get signup_url(invitation_token: invitation.token('wadus@wad.us'), email: 'wadus@wad.us')
      response.status.should == 200
    end
  end

  describe 'user creation' do
    include_context 'organization with users helper'

    DEFAULT_QUOTA_IN_BYTES = 1000

    before(:all) do
      @organization.default_quota_in_bytes = DEFAULT_QUOTA_IN_BYTES
      @organization.save

      @org_2_user_owner = TestUserFactory.new.create_owner(@organization_2)
    end

    before(:each) do
      @organization.whitelisted_email_domains = ['carto.com']
      @organization.auth_username_password_enabled = true
      @organization.auth_google_enabled = true
      @organization.strong_passwords_enabled = true
      @organization.save
    end

    it 'triggers validation error and not a NewUser job if email is not valid' do
      ::Resque.expects(:enqueue).never

      username = unique_name('user')
      email = 'testemail@nonono.com'
      password = '2{Patrañas}'
      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name, user: { username: username, email: email, password: password })
      response.status.should == 422
      Carto::UserCreation.where(username: username).any?.should be_false
    end

    it 'triggers validation error and not a NewUser job if username is too long' do
      ::Resque.expects(:enqueue).never

      name = 'sixtythreecharacterslongiswaytoomanycharactersmatewhydoyoueventry'
      email = "testemail@#{@organization.whitelisted_email_domains[0]}"
      password = '00012345678'
      user = { username: name, email: email, password: password }
      org_name = @organization.name
      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: org_name, user: user)
      response.status.should == 422
      Carto::UserCreation.where(username: name).any?.should be_false
    end

    it 'triggers validation error is password is too short' do
      user = ::User.new

      user.username = 'testusername'
      user.email = 'manolo@escobar.es'
      user.password = 'short'
      user.password_confirmation = user.password

      user.errors[:password].blank?.should == false
    end

    it 'returns 400 error if you attempt username + password signup and it is not valid' do
      @organization.auth_username_password_enabled = false
      @organization.save

      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name, user: { username: 'anewuser', email: "anewuser@#{@organization.whitelisted_email_domains.first}", password: 'password' })
      response.status.should == 400
      ::Resque.expects(:enqueue).never
    end

    it 'triggers a NewUser job with form parameters and default quota and requiring validation email' do
      ::Resque.expects(:enqueue).with(::Resque::UserJobs::Signup::NewUser,
                                      instance_of(String), anything, instance_of(FalseClass)).returns(true)

      username = 'testusername'
      email = "testemail@#{@organization.whitelisted_email_domains[0]}"
      password = '2{Patrañas}'
      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name, user: { username: username, email: email, password: password })
      response.status.should == 200
      last_user_creation = Carto::UserCreation.order('created_at desc').limit(1).first
      last_user_creation.username.should == username
      last_user_creation.email.should == email
      last_user_creation.crypted_password.should_not be_empty
      last_user_creation.organization_id.should == @organization.id
      last_user_creation.quota_in_bytes.should == @organization.default_quota_in_bytes
      last_user_creation.requires_validation_email?.should == true
      last_user_creation.created_via.should == Carto::UserCreation::CREATED_VIA_ORG_SIGNUP
    end

    it 'trigger creation if mail is whitelisted with wildcard' do
      @organization.whitelisted_email_domains = ['*.carto.com']
      @organization.save
      ::Resque.expects(:enqueue).with(::Resque::UserJobs::Signup::NewUser,
                                      instance_of(String), anything, instance_of(FalseClass)).returns(true)
      username = 'testusername'
      email = "testemail@a.carto.com"
      password = '2{Patrañas}'
      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name, user: { username: username, email: email, password: password })
      response.status.should == 200
      last_user_creation = Carto::UserCreation.order('created_at desc').limit(1).first
      last_user_creation.username.should == username
      last_user_creation.email.should == email
      last_user_creation.crypted_password.should_not be_empty
      last_user_creation.organization_id.should == @organization.id
      last_user_creation.quota_in_bytes.should == @organization.default_quota_in_bytes
      last_user_creation.requires_validation_email?.should == true
      last_user_creation.created_via.should == Carto::UserCreation::CREATED_VIA_ORG_SIGNUP
    end

    it 'Returns 422 for not whitelisted domains' do
      ::Resque.expects(:enqueue).never

      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name,
                                        user: { username: 'evil', email: 'evil@whatever.com', password: '2{Patrañas}' })
      response.status.should == 422
    end

    it "doesn't trigger creation if mail domain is not whitelisted and invitation token is wrong" do
      ::Resque.stubs(:enqueue)
      ::Resque.expects(:enqueue).
        with(::Resque::UserJobs::Signup::NewUser, anything, anything, anything).
        never
      invited_email = 'invited_user@whatever.com'
      invitation = Carto::Invitation.create_new(Carto::User.find(@org_user_owner.id), [invited_email], 'W!', false)
      invitation.save

      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(
        user_domain: @organization.name,
        user: { username: 'invited-user', email: invited_email, password: '2{Patrañas}' },
        invitation_token: 'wrong'
      )
      response.status.should == 400
      invitation.reload
      invitation.used_emails.should_not include(invited_email)
    end

    it 'returns 400 if invitation token is for a different organization' do
      invited_email = 'invited_user@whatever.com'
      invitation = Carto::Invitation.create_new(Carto::User.find(@org_2_user_owner.id), [invited_email], 'W!', false)
      invitation.save

      ::Resque.expects(:enqueue).
        with(::Resque::UserJobs::Signup::NewUser, instance_of(String), anything, instance_of(FalseClass)).
        never
      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name,
                                        user: { username: 'invited-user',
                                                email: invited_email,
                                                password: '2{Patrañas}' },
                                        invitation_token: invitation.token(invited_email))
      response.status.should == 400
      invitation.reload
      invitation.used_emails.should_not include(invited_email)
    end

    it 'triggers creation without validation email spending an invitation even if mail domain is not whitelisted' do
      invited_email = 'invited_user@whatever.com'
      invitation = Carto::Invitation.create_new(Carto::User.find(@org_user_owner.id), [invited_email], 'W!', false)
      invitation.save

      ::Resque.expects(:enqueue).
        with(::Resque::UserJobs::Signup::NewUser, instance_of(String), anything, instance_of(FalseClass)).
        returns(true)
      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name,
                                        user: { username: 'invited-user',
                                                email: invited_email,
                                                password: '2{Patrañas}' },
                                        invitation_token: invitation.token(invited_email))
      response.status.should == 200
      last_user_creation = Carto::UserCreation.order('created_at desc').limit(1).first
      @organization.whitelisted_email_domains.should_not include(last_user_creation.email)
      last_user_creation.organization_id.should == @organization.id
      last_user_creation.requires_validation_email?.should == false
      invitation.reload
      invitation.used_emails.should include(invited_email)
    end

    it 'triggers creation invitation twice' do
      invited_email = 'invited_user@whatever.com'

      Carto::Invitation.create_new(
        Carto::User.find(@org_user_owner.id), [invited_email], 'W!', false
      )
      invitation = Carto::Invitation.create_new(
        Carto::User.find(@org_user_owner.id), [invited_email], 'W!', false
      )
      invitation.save

      ::Resque.expects(:enqueue).with(
        ::Resque::UserJobs::Signup::NewUser,
        instance_of(String),
        anything,
        instance_of(FalseClass)
      ).returns(true)

      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(
        user_domain: @organization.name,
        user: { username: 'invited-user',
                email: invited_email,
                password: '2{Patrañas}' },
        invitation_token: invitation.token(invited_email)
      )

      invitation.reload
      invitation.used_emails.should include(invited_email)
    end

    it 'triggers a viewer creation that creates a viewer user' do
      invited_email = 'viewer_user@whatever.com'
      invitation = Carto::Invitation.create_new(Carto::User.find(@org_user_owner.id), [invited_email], 'W!', true)
      invitation.save
      ::Resque.expects(:enqueue).
        with(::Resque::UserJobs::Signup::NewUser, instance_of(String), anything, instance_of(FalseClass)).
        returns(true)

      host! "#{@organization.name}.localhost.lan"
      post signup_organization_user_url(user_domain: @organization.name,
                                        user: { username: 'viewer-user',
                                                email: invited_email,
                                                password: '2{Patrañas}' },
                                        invitation_token: invitation.token(invited_email))
      last_user_creation = Carto::UserCreation.order('created_at desc').limit(1).first
      last_user_creation.next_creation_step until last_user_creation.finished?

      last_user_creation.state.should eq 'success'
      last_user_creation.viewer.should be_true
      last_user_creation.user.viewer.should be_true
    end

    describe 'ldap signup' do

      before(:all) do
        @ldap_configuration = create(:ldap_configuration, { organization_id: @organization.id })
      end

      after(:all) do
        @ldap_configuration.destroy
      end

      it 'returns 404 if ldap is enabled' do

        get signup_organization_user_url(user_domain: @organization.name)
        response.status.should == 404

        post signup_organization_user_url(user_domain: @organization.name, user: { username: 'whatever', email: 'whatever@carto.com', password: 'whatever' })
        response.status.should == 404
      end

    end

    describe 'http authentication signup' do
      include HttpAuthenticationHelper

      describe 'header authentication disabled' do
        it 'returns 404 if http authentication is not set' do
          stub_http_header_authentication_configuration(enabled: false)
          get signup_http_authentication_url
          response.status.should == 404
        end

        it 'returns 404 if http authentication autocreation is disabled' do
          stub_http_header_authentication_configuration(autocreation: false)
          get signup_http_authentication_url
          response.status.should == 404
        end
      end

      describe 'header authentication enabled' do
        it 'returns 404 if http authentication autocreation is disabled' do
          stub_http_header_authentication_configuration(autocreation: false)
          get signup_http_authentication_url
          response.status.should == 404
        end

        it 'returns 500 if http authentication is not set to email' do
          ['auto', 'id', 'username'].each do |field|
            stub_http_header_authentication_configuration(autocreation: true, field: field)
            get signup_http_authentication_url
            response.status.should == 500
          end
        end

        describe 'autocreation enabled' do
          before(:each) do
            stub_http_header_authentication_configuration(autocreation: true)
          end

          it 'returns 403 if http authentication header is not present' do
            get signup_http_authentication_url
            response.status.should == 403
          end

          it 'triggers user creation without organization' do
            email = 'authenticated@whatever.com'

            ::Resque.expects(:enqueue).
              with(::Resque::UserJobs::Signup::NewUser, instance_of(String), anything, instance_of(FalseClass)).
              returns(true)
            get signup_http_authentication_url, {}, authentication_headers(email)
            response.status.should == 200

            last_user_creation = Carto::UserCreation.order('created_at desc').limit(1).first
            last_user_creation.organization_id.should == nil
            last_user_creation.requires_validation_email?.should == false
          end

          it 'triggers user creation with organization' do
            username = "authenticated"
            email = "#{username}@#{@organization.whitelisted_email_domains.first}"

            ::Resque.expects(:enqueue).
              with(::Resque::UserJobs::Signup::NewUser, instance_of(String), anything, instance_of(FalseClass)).
              returns(true)

            host! "#{@organization.name}.localhost.lan"
            get signup_http_authentication_url(user_domain: @organization.name), {}, authentication_headers(email)
            response.status.should == 200

            last_user_creation = Carto::UserCreation.order('created_at desc').limit(1).first
            last_user_creation.organization_id.should == @organization.id
            last_user_creation.requires_validation_email?.should == false
            last_user_creation.username.should == username
            last_user_creation.email.should == email
            last_user_creation.crypted_password.should_not be_empty
          end
        end
      end
    end
  end
end


text:
<?php
  // Link to the start page. Creating it this way, to make application as portable as possible.
  $start_url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/start.php';

  // Check to see if the user is already logged in. If so, send them to the start page
  if($_COOKIE['loggedIn'] == 'true'){
    header("Location: " . $start_url);
  }
?>

 <TITLE>Chapel Attendance</TITLE>

Welcome! Please login.

<form name="login" action="start.php" method="post">

      Password:

      <input type="password" name="password">

      <input type='submit' value="Login" name="login">

</form>


text:
slug: buchanan-ashley
last_name: Buchanan
first_name: Ashley
---
**Ashley Buchanan** is a PhD student in early modern Italian history at the University of South Florida.


text:
"""
Used to analyse ISSGPRS data records with 3GPP parser
"""
from subprocess import Popen, PIPE
import argparse
import string
import sys
import os

class GSMMessageParser(object):
    # Available GSM protocols to parse
    gsm_protocols = {
        'RR':           'gsm_a_ccch',
        'RLC_Uplink':   'gsm_rlcmac_ul',
        'RLC_Downlink': 'gsm_rlcmac_dl',
        'LLC':          'llc',
        'GPRS_LLC':     'gprs_llc',
        'SNDCP':        'sndcp',
        'SNDCP_XID':    'sndcpxid'
    }

    def writeTempPcap(self, message):
        try:
            with open('msg_text.txt', 'w') as msgFile:
                msgFile.write('0000 ' + message)
        except IOError as err:
            sys.stderr.write(err.message)
            return False

        return True

    def call_text2pcap(self, message):

        if self.writeTempPcap(message):
            p = Popen('text2pcap -q -l 147 msg_text.txt pcap_temp.pcap', shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
            p.wait()
            (out, err) = p.communicate()
            if p.returncode:
                print(err)
                return False
        else:
            return False

        os.unlink('msg_text.txt')

        return True

    def call_tshark(self, protocol):
        cmd = 'tshark -r pcap_temp.pcap -Ttext -V -o "uat:user_dlts:\\\"User 0 (DLT=147)\\\",' \
              '\\\"%s\\\",\\\"0\\\",\\\"\\\",\\\"0\\\",\\\"\\\""' % self.gsm_protocols[protocol]
        p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        p.wait()
        (out, err) = p.communicate()
        result = []
        if p.returncode:
            print(err)
            return False
        else:
            result = out.decode('utf-8', 'strict').splitlines()
            os.unlink('pcap_temp.pcap')

        return True, result

    def checkCorrect(self, message, protocol):
        if protocol not in self.gsm_protocols.keys():
            return False

        msg = message.replace(' ', '')
        onlyHex = all(c in string.hexdigits for c in msg)
        pow2 = (len(msg) % 2 == 0)
        if onlyHex and pow2:
            return True

        return False

    def parse(self, arguments):
        res = False
        text = []
        if self.checkCorrect(arguments.message, arguments.protocol):
            if self.call_text2pcap(message=arguments.message):
                res, text = self.call_tshark(protocol=arguments.protocol)

        if res:
            return text
        else:
            return None

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Process messages of 3GPP')
    parser.add_argument('protocol', metavar='Proto', type=str, help='Protocol of specified 3GPP message')
    parser.add_argument('message', metavar='Msg', type=str, help='Hexadecimal string of message octets')
    args = parser.parse_args()
    result = GSMMessageParser().parse(arguments=args)
    for line in result:
        print(line)


text:
package client

import (
	"context"

	acmeutil "github.com/jetstack/cert-manager/pkg/acme/util"

	"golang.org/x/crypto/acme"
)

// Interface is an Automatic Certificate Management Environment (ACME) client
// implementing an Order-based flow.
//
// For more information see https://pkg.go.dev/golang.org/x/crypto/acme#Client
// and RFC 8555 (https://tools.ietf.org/html/rfc8555).
type Interface interface {
	AuthorizeOrder(ctx context.Context, id []acme.AuthzID, opt ...acme.OrderOption) (*acme.Order, error)
	GetOrder(ctx context.Context, url string) (*acme.Order, error)
	FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error)
	FetchCertAlternatives(ctx context.Context, url string, bundle bool) ([][][]byte, error)
	WaitOrder(ctx context.Context, url string) (*acme.Order, error)
	CreateOrderCert(ctx context.Context, finalizeURL string, csr []byte, bundle bool) (der [][]byte, certURL string, err error)
	Accept(ctx context.Context, chal *acme.Challenge) (*acme.Challenge, error)
	GetChallenge(ctx context.Context, url string) (*acme.Challenge, error)
	GetAuthorization(ctx context.Context, url string) (*acme.Authorization, error)
	WaitAuthorization(ctx context.Context, url string) (*acme.Authorization, error)
	Register(ctx context.Context, acct *acme.Account, prompt func(tosURL string) bool) (*acme.Account, error)
	GetReg(ctx context.Context, url string) (*acme.Account, error)
	HTTP01ChallengeResponse(token string) (string, error)
	DNS01ChallengeRecord(token string) (string, error)
	Discover(ctx context.Context) (acme.Directory, error)
	UpdateReg(ctx context.Context, a *acme.Account) (*acme.Account, error)
}

var _ Interface = &acme.Client{
	RetryBackoff: acmeutil.RetryBackoff,
}


text:
# grunt-inline-styles

> Inject external styles to your HTMLs.

## Getting Started
This plugin requires Grunt.

If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:

```shell
npm install grunt-inline-styles --save-dev
```

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:

```js
grunt.loadNpmTasks('grunt-inline-styles');
```

## The "inline_style" task

### Overview
In your project's Gruntfile, add a section named `inline_style` to the data object passed into `grunt.initConfig()`.

```js
grunt.initConfig({
  inline_style: {
    options: {
      // Task-specific options go here.
    },
    your_target: {
      // Target-specific file lists and/or options go here.
    },
  },
})
```

### Options

#### options.verbose
Type: `Boolean`
Default value: `false`

Set true to see more logs about what is happenning.

### Usage Examples

`test.css` file:

```css
/* This is from test.css file */
h1 {
    color:red;
}
```

`test.html` file:

```html
<link href="test.css">

<h1>This should be red</h1>
```

Result is:

```html
<style>/* This is from test.css file */
h1 {
    color:red;
}
</style>

<h1>This should be red</h1>
```

## Release History
- 1.0.0 - Initial release

## License
Copyright (c) 2014 sahibinden.com. Licensed under the MIT license.


text:
package com.mschwartz.bsnstemplate.db;

/**
 * An interface for database entries which are sortable. The sort order is defined by the seq-property.
 * <p>
 * Created by Mike on 9/27/2016.
 *
 * @param <T> the type parameter
 */
public interface IDbSeqEntry<T extends IDbEntry> extends IDbEntry<T> {

    /**
     * Gets seq.
     *
     * @return the seq
     */
    public long getSeq();

    /**
     * Sets seq.
     *
     * @param seq the seq
     */
    public void setSeq(long seq);
}


text:
var optimus = require('../index')

optimus.on('ready', function(app) {
  console.log('optimus::' + app + ':ready');
});

optimus.on('all ready', function() {
  console.log('optimius:::ready');
});

optimus.start({
  status_short: 'cpus',
  status_long: 'cpus',
}, __dirname);