Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Osama/DERG-1399/Add accumulator barriers #286

Merged
merged 16 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/deriv_chart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ library deriv_chart;

export 'generated/l10n.dart';
export 'src/deriv_chart/chart/chart.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/accumulators_horizontal_barrier/accumulators_entry_spot_barrier.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/accumulators_barriers/accumulators_barriers.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/accumulators_barriers/accumulators_entry_spot_barrier.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/barrier.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/horizontal_barrier/combined_barrier.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/horizontal_barrier/horizontal_barrier.dart';
Expand Down
6 changes: 3 additions & 3 deletions lib/src/deriv_chart/chart/basic_chart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ class BasicChartState<T extends BasicChart> extends State<T>

/// Whether the chart data did update or not.
void didUpdateChartData(BasicChart oldChart) {
if (widget.mainSeries.id == oldChart.mainSeries.id &&
widget.mainSeries.didUpdate(oldChart.mainSeries)) {
_playNewTickAnimation();
if (widget.mainSeries.id == oldChart.mainSeries.id) {
widget.mainSeries.didUpdate(oldChart.mainSeries);
}
_playNewTickAnimation();
}

@override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import 'package:deriv_chart/deriv_chart.dart';
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/chart_series/series_painter.dart';
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/models/accumulator_object.dart';

import 'accumulators_barriers_painter.dart';

/// Accumulator Barriers.
class AccumulatorBarriers extends ChartAnnotation<AccumulatorObject> {
/// Initializes a tick indicator.
AccumulatorBarriers(
this.tick, {
required this.lowBarrier,
required this.highBarrier,
required this.highBarrierDisplay,
required this.lowBarrierDisplay,
required this.profit,
required this.barrierSpotDistance,
required this.barrierEpoch,
required this.isActiveContract,
String? id,
}) : super(
id ?? 'AccumulatorTickIndicator',
);

/// The price difference between the barrier and the [tick] quote.
final String barrierSpotDistance;

/// The which this tick indicator will be pointing to.
final Tick tick;

/// The low barrier value.
final double lowBarrier;

/// The high barrier value.
final double highBarrier;

/// The low barrier display value.
final String highBarrierDisplay;

/// The high barrier display value.
final String lowBarrierDisplay;

/// [Optional] The profit value which is being shown in the middle of the tick indicator.
final String? profit;

/// The [epoch] of the tick that the barriers belong to.
final int barrierEpoch;

/// Weathers there is an active contract or not.
final bool isActiveContract;

@override
SeriesPainter<Series> createPainter() => AccumulatorBarriersPainter(this);

@override
AccumulatorObject createObject() => AccumulatorObject(
tick: tick,
barrierEpoch: barrierEpoch,
lowBarrier: lowBarrier,
highBarrier: highBarrier,
);

@override
int? getMaxEpoch() => barrierEpoch;

@override
int? getMinEpoch() => barrierEpoch;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import 'dart:ui' as ui;

import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/annotations/barriers/accumulators_barriers/accumulators_barriers.dart';
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/chart_data.dart';
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/chart_series/series_painter.dart';
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/models/accumulator_object.dart';
import 'package:deriv_chart/src/deriv_chart/chart/data_visualization/models/animation_info.dart';
import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_dot.dart';
import 'package:deriv_chart/src/deriv_chart/chart/helpers/paint_functions/paint_text.dart';
import 'package:flutter/material.dart';

/// Accumulator barriers painter.
class AccumulatorBarriersPainter extends SeriesPainter<AccumulatorBarriers> {
/// Initializes [AccumulatorBarriersPainter].
AccumulatorBarriersPainter(super.series);

/// Initializes [AccumulatorBarriersPainter].

final Paint _linePaint = Paint()
..strokeWidth = 1
..color = Colors.grey
..style = PaintingStyle.stroke;

final Paint _linePaintFill = Paint()
..strokeWidth = 1
..color = Colors.grey
..style = PaintingStyle.fill;

final Paint _rectPaint = Paint()
..color =
Colors.grey.withOpacity(0.08) // Set the alpha value for transparency
..style = PaintingStyle.fill;

@override
void onPaint({
required Canvas canvas,
required Size size,
required EpochToX epochToX,
required QuoteToY quoteToY,
required AnimationInfo animationInfo,
}) {
// Change the barrier color based on the contract status and tick quote.

Color color = theme.base03Color;
if (series.isActiveContract) {
color = theme.accentGreenColor;
}

if (series.tick.quote > series.highBarrier ||
series.tick.quote < series.lowBarrier) {
color = theme.accentRedColor;
}
_linePaint.color = color;
_linePaintFill.color = color;
_rectPaint.color = color.withOpacity(0.08);

final AccumulatorBarriers indicator = series;

double barrierX = epochToX(indicator.barrierEpoch);
double hBarrierY = indicator.highBarrier;
double lBarrierY = indicator.lowBarrier;

if (indicator.previousObject != null) {
final AccumulatorObject? previousIndicator = indicator.previousObject;

barrierX = ui.lerpDouble(
epochToX(previousIndicator!.barrierEpoch),
epochToX(indicator.barrierEpoch),
animationInfo.currentTickPercent,
) ??
barrierX;

hBarrierY = ui.lerpDouble(
previousIndicator.highBarrier,
indicator.highBarrier,
animationInfo.currentTickPercent,
) ??
hBarrierY;

lBarrierY = ui.lerpDouble(
previousIndicator.lowBarrier,
indicator.lowBarrier,
animationInfo.currentTickPercent,
) ??
lBarrierY;
}
final Offset highBarrierPosition = Offset(
barrierX,
quoteToY(hBarrierY),
);

final Offset lowBarrierPosition = Offset(
barrierX,
quoteToY(lBarrierY),
);

const int triangleEdge = 4;
const int triangleHeight = 5;

final Path upperTrianglePath = Path()
..moveTo(
highBarrierPosition.dx,
highBarrierPosition.dy,
)
..lineTo(
highBarrierPosition.dx + triangleEdge,
highBarrierPosition.dy,
)
..lineTo(
highBarrierPosition.dx,
highBarrierPosition.dy + triangleHeight,
)
..lineTo(
highBarrierPosition.dx + -triangleEdge,
highBarrierPosition.dy,
)
..close();

final Path lowerTrianglePath = Path()
..moveTo(
lowBarrierPosition.dx,
lowBarrierPosition.dy,
)
..lineTo(
lowBarrierPosition.dx + triangleEdge,
lowBarrierPosition.dy,
)
..lineTo(
lowBarrierPosition.dx,
lowBarrierPosition.dy - triangleHeight,
)
..lineTo(
lowBarrierPosition.dx + -triangleEdge,
lowBarrierPosition.dy,
)
..close();

canvas
..drawLine(
lowBarrierPosition,
Offset(size.width, lowBarrierPosition.dy),
_linePaint,
)
..drawLine(
highBarrierPosition,
Offset(size.width, highBarrierPosition.dy),
_linePaint,
);

if (indicator.tick.epoch != indicator.barrierEpoch) {
_paintBlinkingGlow(
canvas,
epochToX(indicator.barrierEpoch),
quoteToY(indicator.lowBarrier +
((indicator.highBarrier - indicator.lowBarrier) / 2)),
animationInfo,
Colors.grey,
);
}

canvas
..drawPath(upperTrianglePath, _linePaint)
..drawPath(lowerTrianglePath, _linePaint)
..drawPath(upperTrianglePath, _linePaintFill)
..drawPath(lowerTrianglePath, _linePaintFill);

paintText(
canvas,
text: '-${indicator.barrierSpotDistance}',
anchor: lowBarrierPosition + const Offset(30, 10),
style: TextStyle(color: color, fontSize: 12),
);

paintText(
canvas,
text: '+${indicator.barrierSpotDistance}',
anchor: highBarrierPosition + const Offset(30, -10),
style: TextStyle(color: color, fontSize: 12),
);

final Rect rect = Rect.fromPoints(
highBarrierPosition, Offset(size.width, lowBarrierPosition.dy));
canvas.drawRect(rect, _rectPaint);
}

void _paintBlinkingGlow(
Canvas canvas,
double dotX,
double y,
AnimationInfo animationInfo,
Color color,
) {
paintBlinkingGlow(
canvas,
Offset(dotX, y),
animationInfo.blinkingPercent,
color,
);
paintBlinkingGlow(
canvas,
Offset(dotX, y),
animationInfo.blinkingPercent,
color,
fullSize: 6,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:deriv_chart/deriv_chart.dart';

/// A [ChartObject] for defining position of a horizontal barrier.
class AccumulatorObject extends ChartObject {
/// Initializes a [ChartObject] for defining position of a horizontal barrier.
const AccumulatorObject({
required this.tick,
required this.barrierEpoch,
required this.lowBarrier,
required this.highBarrier,
}) : super(barrierEpoch, null, lowBarrier, highBarrier);

/// The which this tick indicator will be pointing to.
final Tick tick;

/// The low barrier value.
final double lowBarrier;

/// The high barrier value.
final double highBarrier;

/// The [epoch] of the tick that the barriers belong to.
final int barrierEpoch;

@override
bool operator ==(covariant AccumulatorObject other) =>
tick == other.tick &&
barrierEpoch == other.barrierEpoch &&
lowBarrier == other.lowBarrier &&
highBarrier == other.highBarrier;

@override
int get hashCode => Object.hash(tick, barrierEpoch, lowBarrier, highBarrier);
}
10 changes: 6 additions & 4 deletions lib/src/deriv_chart/chart/helpers/paint_functions/paint_dot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ void paintBlinkingGlow(
Canvas canvas,
Offset center,
double animationProgress,
Color color,
) =>
Color color, {
int fullSize = 12,
int alpha = 50,
}) =>
canvas.drawCircle(
center,
12 * animationProgress,
Paint()..color = color.withAlpha(50),
fullSize * animationProgress,
Paint()..color = color.withAlpha(alpha),
);

/// Paints a dot on [center].
Expand Down