<commit_before>import Foundation
import UIKit
import RxSwift

class GroupRenderer: NodeRenderer {
	var ctx: RenderContext
	var node: Node {
		get { return group }
	}

	var animationCache: AnimationCache

	let group: Group
	let disposeBag = DisposeBag()

	init(group: Group, ctx: RenderContext, animationCache: AnimationCache) {
		self.group = group
		self.ctx = ctx
		self.animationCache = animationCache

		hook()
	}

	func hook() {
		func onGroupChange(new: [Node]) {
			ctx.view?.setNeedsDisplay()
		}

		group.contents.rx_elements().subscribeNext { new in
			onGroupChange(new)
		}.addDisposableTo(disposeBag)
	}

	func render(force: Bool, opacity: Double) {

		if !force {

			// Cutting animated content
			if animationCache.isAnimating(group) {
				return
			}
		}

		let staticContents = group.contents.filter { !animationCache.isAnimating($0) }

		let contentRenderers = staticContents.map { RenderUtils.createNodeRenderer($0, context: ctx, animationCache: animationCache) }
        
        CGContextConcatCTM(ctx.cgContext, RenderUtils.mapTransform(self.node.place))
        
		contentRenderers.forEach { renderer in
			CGContextSaveGState(ctx.cgContext)
            if !(renderer.node is Group) {
                CGContextConcatCTM(ctx.cgContext, RenderUtils.mapTransform(renderer.node.place))
            }
			setClip(renderer.node)
			renderer.render(force, opacity: renderer.node.opacity * opacity)
			CGContextRestoreGState(ctx.cgContext)
		}
	}

	func detectTouches(location: CGPoint) -> [Shape] {
		var touchedShapes = [Shape]()
		let staticContents = group.contents.filter { !animationCache.isAnimating($0) }

		let contentRenderers = staticContents.map { RenderUtils.createNodeRenderer($0, context: ctx, animationCache: animationCache) }
<commit_msg>revert GroupRenderer changes<commit_after>import Foundation
import UIKit
import RxSwift

class GroupRenderer: NodeRenderer {
	var ctx: RenderContext
	var node: Node {
		get { return group }
	}

	var animationCache: AnimationCache

	let group: Group
	let disposeBag = DisposeBag()

	init(group: Group, ctx: RenderContext, animationCache: AnimationCache) {
		self.group = group
		self.ctx = ctx
		self.animationCache = animationCache

		hook()
	}

	func hook() {
		func onGroupChange(new: [Node]) {
			ctx.view?.setNeedsDisplay()
		}

		group.contents.rx_elements().subscribeNext { new in
			onGroupChange(new)
		}.addDisposableTo(disposeBag)
	}

	func render(force: Bool, opacity: Double) {

		if !force {

			// Cutting animated content
			if animationCache.isAnimating(group) {
				return
			}
		}

		let staticContents = group.contents.filter { !animationCache.isAnimating($0) }

		let contentRenderers = staticContents.map { RenderUtils.createNodeRenderer($0, context: ctx, animationCache: animationCache) }
        
		contentRenderers.forEach { renderer in
			CGContextSaveGState(ctx.cgContext)
            CGContextConcatCTM(ctx.cgContext, RenderUtils.mapTransform(renderer.node.place))
			setClip(renderer.node)
			renderer.render(force, opacity: renderer.node.opacity * opacity)
			CGContextRestoreGState(ctx.cgContext)
		}
	}

	func detectTouches(location: CGPoint) -> [Shape] {
		var touchedShapes = [Shape]()
		let staticContents = group.contents.filter { !animationCache.isAnimating($0) }

		let contentRenderers = staticContents.map { RenderUtils.createNodeRenderer($0, context: ctx, animationCache: animationCache) }

{'fraction_non_alphanumeric': 0.10088235294117646, 'fraction_numerical': 0.002352941176470588, 'mean_word_length': 4.19236641221374, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3809464', 'n_tokens_mistral': 1141, 'n_tokens_neox': 1041, 'n_words': 222}